From b96192eec6f64a254ef9c3b51f11e5aac8a3b24d Mon Sep 17 00:00:00 2001
From: chris48s <chris48s@users.noreply.github.com>
Date: Sat, 15 Apr 2023 20:17:35 +0100
Subject: [PATCH] remove redis token persistence backend (#9065)

* remove redis token persistence backend

* error and exit if redis_url is set
---
 .github/workflows/test-integration-17.yml     |   9 -
 .github/workflows/test-integration.yml        |   9 -
 CONTRIBUTING.md                               |   5 +-
 .../local-shields-io-production.template.yml  |   1 -
 .../redis-token-persistence.integration.js    |  94 --------
 core/token-pooling/redis-token-persistence.js |  57 -----
 package-lock.json                             | 211 ------------------
 package.json                                  |   2 -
 scripts/redis-connectivity-test.js            |  24 --
 server.js                                     |   8 +-
 services/github/github-constellation.js       |  13 +-
 11 files changed, 6 insertions(+), 427 deletions(-)
 delete mode 100644 core/token-pooling/redis-token-persistence.integration.js
 delete mode 100644 core/token-pooling/redis-token-persistence.js
 delete mode 100644 scripts/redis-connectivity-test.js

diff --git a/.github/workflows/test-integration-17.yml b/.github/workflows/test-integration-17.yml
index 45394fc977..ccec28fb8d 100644
--- a/.github/workflows/test-integration-17.yml
+++ b/.github/workflows/test-integration-17.yml
@@ -14,15 +14,6 @@ jobs:
       PAT_EXISTS: ${{ secrets.GH_PAT != '' }}
 
     services:
-      redis:
-        image: redis
-        options: >-
-          --health-cmd "redis-cli ping"
-          --health-interval 10s
-          --health-timeout 5s
-          --health-retries 5
-        ports:
-          - 6379:6379
       postgres:
         image: postgres
         env:
diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml
index d7e6467848..b86b9a4346 100644
--- a/.github/workflows/test-integration.yml
+++ b/.github/workflows/test-integration.yml
@@ -14,15 +14,6 @@ jobs:
       PAT_EXISTS: ${{ secrets.GH_PAT != '' }}
 
     services:
-      redis:
-        image: redis
-        options: >-
-          --health-cmd "redis-cli ping"
-          --health-interval 10s
-          --health-timeout 5s
-          --health-retries 5
-        ports:
-          - 6379:6379
       postgres:
         image: postgres
         env:
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 549a3162c0..9a610913f0 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -134,12 +134,11 @@ Prettier before a commit by default.
 When adding or changing a service [please write tests][service-tests], and ensure the [title of your Pull Requests follows the required conventions](#running-service-tests-in-pull-requests) to ensure your tests are executed.
 When changing other code, please add unit tests.
 
-The integration tests are not run by default. For most contributions it is OK to skip these unless you're working directly on the code for storing the GitHub token pool in postgres/redis.
+The integration tests are not run by default. For most contributions it is OK to skip these unless you're working directly on the code for storing the GitHub token pool in postgres.
 
 To run the integration tests:
 
-- You must have Redis installed and in your PATH. Use `brew install redis`, `apt-get install redis`, etc. The test runner will start the server automatically.
-- You must also have PostgreSQL installed. Use `brew install postgresql`, `apt-get install postgresql`, etc.
+- You must have PostgreSQL installed. Use `brew install postgresql`, `apt-get install postgresql`, etc.
 - Set a connection string either with an env var `POSTGRES_URL=postgresql://user:pass@127.0.0.1:5432/db_name` or by using
   ```yaml
   private:
diff --git a/config/local-shields-io-production.template.yml b/config/local-shields-io-production.template.yml
index efb5514628..848039ad7a 100644
--- a/config/local-shields-io-production.template.yml
+++ b/config/local-shields-io-production.template.yml
@@ -4,7 +4,6 @@ private:
   gh_client_id: ...
   gh_client_secret: ...
   gitlab_token: ...
-  redis_url: ...
   sentry_dsn: ...
   shields_secret: ...
   sl_insight_userUuid: ...
diff --git a/core/token-pooling/redis-token-persistence.integration.js b/core/token-pooling/redis-token-persistence.integration.js
deleted file mode 100644
index b11d9304bb..0000000000
--- a/core/token-pooling/redis-token-persistence.integration.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import RedisServer from 'redis-server'
-import Redis from 'ioredis'
-import { expect } from 'chai'
-import RedisTokenPersistence from './redis-token-persistence.js'
-
-describe('Redis token persistence', function () {
-  let server
-  // In CI, expect redis already to be running.
-  if (!process.env.CI) {
-    beforeEach(async function () {
-      server = new RedisServer({ config: { host: 'localhost' } })
-      await server.open()
-    })
-  }
-
-  const key = 'tokenPersistenceIntegrationTest'
-
-  let redis
-  beforeEach(async function () {
-    redis = new Redis()
-    await redis.del(key)
-  })
-  afterEach(async function () {
-    if (redis) {
-      await redis.quit()
-      redis = undefined
-    }
-  })
-
-  if (!process.env.CI) {
-    afterEach(async function () {
-      await server.close()
-      server = undefined
-    })
-  }
-
-  let persistence
-  beforeEach(function () {
-    persistence = new RedisTokenPersistence({ key })
-  })
-  afterEach(async function () {
-    if (persistence) {
-      await persistence.stop()
-      persistence = undefined
-    }
-  })
-
-  context('when the key does not exist', function () {
-    it('does nothing', async function () {
-      const tokens = await persistence.initialize()
-      expect(tokens).to.deep.equal([])
-    })
-  })
-
-  context('when the key exists', function () {
-    const initialTokens = ['a', 'b', 'c'].map(char => char.repeat(40))
-
-    beforeEach(async function () {
-      await redis.sadd(key, initialTokens)
-    })
-
-    it('loads the contents', async function () {
-      const tokens = await persistence.initialize()
-      expect(tokens.sort()).to.deep.equal(initialTokens)
-    })
-
-    context('when tokens are added', function () {
-      it('saves the change', async function () {
-        const newToken = 'e'.repeat(40)
-        const expected = initialTokens.slice()
-        expected.push(newToken)
-
-        await persistence.initialize()
-        await persistence.noteTokenAdded(newToken)
-
-        const savedTokens = await redis.smembers(key)
-        expect(savedTokens.sort()).to.deep.equal(expected)
-      })
-    })
-
-    context('when tokens are removed', function () {
-      it('saves the change', async function () {
-        const expected = Array.from(initialTokens)
-        const toRemove = expected.pop()
-
-        await persistence.initialize()
-        await persistence.noteTokenRemoved(toRemove)
-
-        const savedTokens = await redis.smembers(key)
-        expect(savedTokens.sort()).to.deep.equal(expected)
-      })
-    })
-  })
-})
diff --git a/core/token-pooling/redis-token-persistence.js b/core/token-pooling/redis-token-persistence.js
deleted file mode 100644
index dd0b6fb306..0000000000
--- a/core/token-pooling/redis-token-persistence.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import { URL } from 'url'
-import Redis from 'ioredis'
-import log from '../server/log.js'
-
-export default class RedisTokenPersistence {
-  constructor({ url, key }) {
-    this.url = url
-    this.key = key
-    this.noteTokenAdded = this.noteTokenAdded.bind(this)
-    this.noteTokenRemoved = this.noteTokenRemoved.bind(this)
-  }
-
-  async initialize() {
-    const options =
-      this.url && this.url.startsWith('rediss:')
-        ? {
-            //  https://www.compose.com/articles/ssl-connections-arrive-for-redis-on-compose/
-            tls: { servername: new URL(this.url).hostname },
-          }
-        : undefined
-    this.redis = new Redis(this.url, options)
-    this.redis.on('error', e => {
-      log.error(e)
-    })
-
-    const tokens = await this.redis.smembers(this.key)
-    return tokens
-  }
-
-  async stop() {
-    await this.redis.quit()
-  }
-
-  async onTokenAdded(token) {
-    await this.redis.sadd(this.key, token)
-  }
-
-  async onTokenRemoved(token) {
-    await this.redis.srem(this.key, token)
-  }
-
-  async noteTokenAdded(token) {
-    try {
-      await this.onTokenAdded(token)
-    } catch (e) {
-      log.error(e)
-    }
-  }
-
-  async noteTokenRemoved(token) {
-    try {
-      await this.onTokenRemoved(token)
-    } catch (e) {
-      log.error(e)
-    }
-  }
-}
diff --git a/package-lock.json b/package-lock.json
index 2c78c4456f..63e2991b0a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -33,7 +33,6 @@
         "got": "^12.6.0",
         "graphql": "^15.6.1",
         "graphql-tag": "^2.12.6",
-        "ioredis": "5.3.1",
         "joi": "17.9.1",
         "joi-extension-semver": "5.0.0",
         "js-yaml": "^4.1.0",
@@ -144,7 +143,6 @@
         "react-pose": "^4.0.10",
         "react-select": "^4.3.1",
         "read-all-stdin-sync": "^1.0.5",
-        "redis-server": "^1.2.2",
         "rimraf": "^4.4.1",
         "sazerac": "^2.0.0",
         "simple-git-hooks": "^2.8.1",
@@ -3532,11 +3530,6 @@
       "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
       "dev": true
     },
-    "node_modules/@ioredis/commands": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.1.1.tgz",
-      "integrity": "sha512-fsR4P/ROllzf/7lXYyElUJCheWdTJVJvOTps8v9IWKFATxR61ANOlnoPqhH099xYLrJGpc2ZQ28B3rMeUt5VQg=="
-    },
     "node_modules/@istanbuljs/schema": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
@@ -9150,14 +9143,6 @@
         "range_check": "^1.4.0"
       }
     },
-    "node_modules/cluster-key-slot": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
-      "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw==",
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/color": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
@@ -11023,14 +11008,6 @@
         "node": ">=0.4.0"
       }
     },
-    "node_modules/denque": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
-      "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
     "node_modules/depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -18110,50 +18087,6 @@
         "loose-envify": "^1.0.0"
       }
     },
-    "node_modules/ioredis": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.1.tgz",
-      "integrity": "sha512-C+IBcMysM6v52pTLItYMeV4Hz7uriGtoJdz7SSBDX6u+zwSYGirLdQh3L7t/OItWITcw3gTFMjJReYUwS4zihg==",
-      "dependencies": {
-        "@ioredis/commands": "^1.1.1",
-        "cluster-key-slot": "^1.1.0",
-        "debug": "^4.3.4",
-        "denque": "^2.1.0",
-        "lodash.defaults": "^4.2.0",
-        "lodash.isarguments": "^3.1.0",
-        "redis-errors": "^1.2.0",
-        "redis-parser": "^3.0.0",
-        "standard-as-callback": "^2.1.0"
-      },
-      "engines": {
-        "node": ">=12.22.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/ioredis"
-      }
-    },
-    "node_modules/ioredis/node_modules/debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dependencies": {
-        "ms": "2.1.2"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/ioredis/node_modules/ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-    },
     "node_modules/ip6": {
       "version": "0.0.4",
       "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.0.4.tgz",
@@ -20066,11 +19999,6 @@
       "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=",
       "dev": true
     },
-    "node_modules/lodash.defaults": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
-    },
     "node_modules/lodash.difference": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
@@ -20124,11 +20052,6 @@
       "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
       "dev": true
     },
-    "node_modules/lodash.isarguments": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
-      "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
-    },
     "node_modules/lodash.isfunction": {
       "version": "3.0.9",
       "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
@@ -24463,15 +24386,6 @@
       "integrity": "sha1-2chtPcTcLfkBboiUbe/Wm0m0EWI=",
       "dev": true
     },
-    "node_modules/promise-queue": {
-      "version": "2.2.5",
-      "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz",
-      "integrity": "sha1-L29ffA9tCBCelnZZx5uIqe1ek7Q=",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
     "node_modules/prompts": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -25538,37 +25452,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/redis-errors": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
-      "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=",
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/redis-parser": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
-      "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
-      "dependencies": {
-        "redis-errors": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/redis-server": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/redis-server/-/redis-server-1.2.2.tgz",
-      "integrity": "sha512-pOaSIeSMVFkEFIuaMtpQ3TOr3uI4sUmEHm4ofGks5vTPRseHUszxyIlC70IFjUR9qSeH8o/ARZEM8dqcJmgGJw==",
-      "dev": true,
-      "dependencies": {
-        "promise-queue": "^2.2.5"
-      },
-      "engines": {
-        "node": ">=4.0.0"
-      }
-    },
     "node_modules/redux": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
@@ -27596,11 +27479,6 @@
       "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
       "dev": true
     },
-    "node_modules/standard-as-callback": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
-      "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
-    },
     "node_modules/start-server-and-test": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.0.tgz",
@@ -33448,11 +33326,6 @@
       "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
       "dev": true
     },
-    "@ioredis/commands": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.1.1.tgz",
-      "integrity": "sha512-fsR4P/ROllzf/7lXYyElUJCheWdTJVJvOTps8v9IWKFATxR61ANOlnoPqhH099xYLrJGpc2ZQ28B3rMeUt5VQg=="
-    },
     "@istanbuljs/schema": {
       "version": "0.1.3",
       "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
@@ -37697,11 +37570,6 @@
         "range_check": "^1.4.0"
       }
     },
-    "cluster-key-slot": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.0.tgz",
-      "integrity": "sha512-2Nii8p3RwAPiFwsnZvukotvow2rIHM+yQ6ZcBXGHdniadkYGZYiGmkHJIbZPIV9nfv7m/U1IPMVVcAhoWFeklw=="
-    },
     "color": {
       "version": "3.1.3",
       "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
@@ -39122,11 +38990,6 @@
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
       "dev": true
     },
-    "denque": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
-      "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
-    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -44471,37 +44334,6 @@
         "loose-envify": "^1.0.0"
       }
     },
-    "ioredis": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.1.tgz",
-      "integrity": "sha512-C+IBcMysM6v52pTLItYMeV4Hz7uriGtoJdz7SSBDX6u+zwSYGirLdQh3L7t/OItWITcw3gTFMjJReYUwS4zihg==",
-      "requires": {
-        "@ioredis/commands": "^1.1.1",
-        "cluster-key-slot": "^1.1.0",
-        "debug": "^4.3.4",
-        "denque": "^2.1.0",
-        "lodash.defaults": "^4.2.0",
-        "lodash.isarguments": "^3.1.0",
-        "redis-errors": "^1.2.0",
-        "redis-parser": "^3.0.0",
-        "standard-as-callback": "^2.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "4.3.4",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-          "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-          "requires": {
-            "ms": "2.1.2"
-          }
-        },
-        "ms": {
-          "version": "2.1.2",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-          "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
-        }
-      }
-    },
     "ip6": {
       "version": "0.0.4",
       "resolved": "https://registry.npmjs.org/ip6/-/ip6-0.0.4.tgz",
@@ -45961,11 +45793,6 @@
       "integrity": "sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s=",
       "dev": true
     },
-    "lodash.defaults": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
-      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
-    },
     "lodash.difference": {
       "version": "4.5.0",
       "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz",
@@ -46019,11 +45846,6 @@
       "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
       "dev": true
     },
-    "lodash.isarguments": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
-      "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo="
-    },
     "lodash.isfunction": {
       "version": "3.0.9",
       "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
@@ -49303,12 +49125,6 @@
       "integrity": "sha1-2chtPcTcLfkBboiUbe/Wm0m0EWI=",
       "dev": true
     },
-    "promise-queue": {
-      "version": "2.2.5",
-      "resolved": "https://registry.npmjs.org/promise-queue/-/promise-queue-2.2.5.tgz",
-      "integrity": "sha1-L29ffA9tCBCelnZZx5uIqe1ek7Q=",
-      "dev": true
-    },
     "prompts": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
@@ -50122,28 +49938,6 @@
         }
       }
     },
-    "redis-errors": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
-      "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
-    },
-    "redis-parser": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
-      "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
-      "requires": {
-        "redis-errors": "^1.0.0"
-      }
-    },
-    "redis-server": {
-      "version": "1.2.2",
-      "resolved": "https://registry.npmjs.org/redis-server/-/redis-server-1.2.2.tgz",
-      "integrity": "sha512-pOaSIeSMVFkEFIuaMtpQ3TOr3uI4sUmEHm4ofGks5vTPRseHUszxyIlC70IFjUR9qSeH8o/ARZEM8dqcJmgGJw==",
-      "dev": true,
-      "requires": {
-        "promise-queue": "^2.2.5"
-      }
-    },
     "redux": {
       "version": "4.1.2",
       "resolved": "https://registry.npmjs.org/redux/-/redux-4.1.2.tgz",
@@ -51799,11 +51593,6 @@
       "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
       "dev": true
     },
-    "standard-as-callback": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
-      "integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
-    },
     "start-server-and-test": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.0.tgz",
diff --git a/package.json b/package.json
index c58e325fe5..43aef1a5f7 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,6 @@
     "got": "^12.6.0",
     "graphql": "^15.6.1",
     "graphql-tag": "^2.12.6",
-    "ioredis": "5.3.1",
     "joi": "17.9.1",
     "joi-extension-semver": "5.0.0",
     "js-yaml": "^4.1.0",
@@ -231,7 +230,6 @@
     "react-pose": "^4.0.10",
     "react-select": "^4.3.1",
     "read-all-stdin-sync": "^1.0.5",
-    "redis-server": "^1.2.2",
     "rimraf": "^4.4.1",
     "sazerac": "^2.0.0",
     "simple-git-hooks": "^2.8.1",
diff --git a/scripts/redis-connectivity-test.js b/scripts/redis-connectivity-test.js
deleted file mode 100644
index 5e61fd5cdf..0000000000
--- a/scripts/redis-connectivity-test.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import config from 'config'
-import GithubConstellation from '../services/github/github-constellation.js'
-const objectConfig = config.util.toObject()
-console.log(objectConfig)
-
-const { persistence } = new GithubConstellation({
-  service: objectConfig.public.services.github,
-  private: objectConfig.private,
-})
-
-async function main() {
-  const tokens = await persistence.initialize()
-  console.log(`${tokens.length} tokens loaded`)
-  await persistence.stop()
-}
-
-;(async () => {
-  try {
-    await main()
-  } catch (e) {
-    console.error(e)
-    process.exit(1)
-  }
-})()
diff --git a/server.js b/server.js
index cc7b3684d0..a339dc2679 100644
--- a/server.js
+++ b/server.js
@@ -43,12 +43,10 @@ if (fs.existsSync('.env')) {
 }
 
 if (config.private.redis_url != null) {
-  console.warn(
-    'RedisTokenPersistence is deprecated for token pooling and will be removed in a future release. Migrate to SqlTokenPersistence'
-  )
-  console.warn(
-    'See https://github.com/badges/shields/blob/master/CHANGELOG.md#server-2023-03-01 for more info'
+  console.error(
+    'RedisTokenPersistence has been removed. Migrate to SqlTokenPersistence'
   )
+  process.exit(1)
 }
 
 const legacySecretsPath = path.join(
diff --git a/services/github/github-constellation.js b/services/github/github-constellation.js
index f229185aa8..9e7b1a4a44 100644
--- a/services/github/github-constellation.js
+++ b/services/github/github-constellation.js
@@ -1,5 +1,4 @@
 import { AuthHelper } from '../../core/base-service/auth-helper.js'
-import RedisTokenPersistence from '../../core/token-pooling/redis-token-persistence.js'
 import SqlTokenPersistence from '../../core/token-pooling/sql-token-persistence.js'
 import log from '../../core/server/log.js'
 import GithubApiProvider from './github-api-provider.js'
@@ -24,23 +23,13 @@ class GithubConstellation {
     this._debugEnabled = config.service.debug.enabled
     this._debugIntervalSeconds = config.service.debug.intervalSeconds
 
-    const {
-      postgres_url: pgUrl,
-      redis_url: redisUrl,
-      gh_token: globalToken,
-    } = config.private
+    const { postgres_url: pgUrl, gh_token: globalToken } = config.private
     if (pgUrl) {
       log.log('Token persistence configured with dbUrl')
       this.persistence = new SqlTokenPersistence({
         url: pgUrl,
         table: 'github_user_tokens',
       })
-    } else if (redisUrl) {
-      log.log('Token persistence configured with redisUrl')
-      this.persistence = new RedisTokenPersistence({
-        url: redisUrl,
-        key: 'githubUserTokens',
-      })
     }
 
     this.apiProvider = new GithubApiProvider({
-- 
GitLab