diff --git a/.env.defaults b/.env.defaults
index 76d680e0621515e4c2bde4491f5a781ace24cc2e..d25e90d6b7fd6325a102387c0db15430be8b11a0 100644
--- a/.env.defaults
+++ b/.env.defaults
@@ -3,5 +3,8 @@ CACHE_TTL=30000
 PORT=8080
 LOG_LEVEL=info
 APP_ROOT=/
+EXPOSE_API_DOCS=false
 
+REDIS_PORT=6379
+REDIS_DB=0
 REDIS_PREFIX=ui-middleware
diff --git a/helm/core-ui-middleware/templates/deployment.yaml b/helm/core-ui-middleware/templates/deployment.yaml
index 5bc305a3c947c6dd5ecb7f9061ebbcefb9cbc9ba..f3508e57dc81a58d91c69ac6f5beb73be735695c 100644
--- a/helm/core-ui-middleware/templates/deployment.yaml
+++ b/helm/core-ui-middleware/templates/deployment.yaml
@@ -46,14 +46,14 @@ spec:
           {{- if .Values.probe.liveness.enabled }}
           livenessProbe:
             httpGet:
-              path: {{ .Values.appRoot }}healthy
+              path: live
               port: http
             {{- omit .Values.probe.liveness "enabled" | toYaml | nindent 12 }}
           {{- end }}
           {{- if .Values.probe.readiness.enabled }}
           readinessProbe:
             httpGet:
-                path: {{ .Values.appRoot }}ready
+                path: ready
                 port: http
             {{- omit .Values.probe.readiness "enabled" | toYaml | nindent 12 }}
           {{- end }}
diff --git a/integration/caching_test.js b/integration/caching_test.js
index a4b831e07dbd817b1e49f339935430fd21c4634d..e50058013aafa93b31b0415b7469b37753799d91 100644
--- a/integration/caching_test.js
+++ b/integration/caching_test.js
@@ -28,7 +28,7 @@ describe('File caching service', function () {
   })
 
   it('caches manifest data', async function () {
-    const response = await request(app).get('/manifests')
+    const response = await request(app.server).get('/manifests')
     expect(response.statusCode).to.equal(200)
     const version = response.headers.version
 
@@ -37,11 +37,11 @@ describe('File caching service', function () {
   })
 
   it('caches html files', async function () {
-    const response = await request(app).get('/index.html')
+    const response = await request(app.server).get('/index.html')
     expect(response.statusCode).to.equal(200)
     const version = response.headers.version
 
-    const body = await client.getBuffer(getRedisKey({ version, name: '/index.html:body' }))
+    const body = (await client.getBuffer(getRedisKey({ version, name: '/index.html:body' }))) || ''
     expect(gunzipSync(body).toString()).to.equal('<html><head></head><body>it\'s me</body></html>')
     const meta = await client.get(getRedisKey({ version, name: '/index.html:meta' }))
     expect(meta).to.equal('{"headers":{"content-type":"text/html","dependencies":false,"content-encoding":"gzip"}}')
@@ -52,14 +52,14 @@ describe('File caching service', function () {
     await client.set(getRedisKey({ version, name: '/demo.js:meta' }), '{"headers":{"content-type":"application/javascript","dependencies":false}}')
     await client.set(getRedisKey({ version, name: '/demo.js:body' }), 'console.log("Demo")')
 
-    const response = await request(app).get('/demo.js').set('version', version)
+    const response = await request(app.server).get('/demo.js').set('version', version)
     expect(response.statusCode).to.equal(200)
 
     // just for testing purposes, delete the keys from redis to make sure, it is served from local cache
     await client.del(getRedisKey({ version, name: '/demo.js:meta' }))
     await client.del(getRedisKey({ version, name: '/demo.js:body' }))
 
-    const response2 = await request(app).get('/demo.js').set('version', version)
+    const response2 = await request(app.server).get('/demo.js').set('version', version)
     expect(response2.statusCode).to.equal(200)
   })
 })
diff --git a/integration/config_test.js b/integration/config_test.js
index 87ed9dc24e96107034f7f9276fc056eee1fab8fa..de0cbdfd60d9d9d59431d58579916085b8089b99 100644
--- a/integration/config_test.js
+++ b/integration/config_test.js
@@ -11,7 +11,7 @@ describe('Configuration', function () {
 
   beforeEach(async function () {
     // need to set the redis-prefix. Otherwise, the bull workers will interfere
-    process.env.REDIS_PREFIX = Math.random()
+    process.env.REDIS_PREFIX = Math.random().toString()
     await client.flushdb()
     mockConfig(config = { urls: ['http://ui-server/'] })
     mockFetch({
@@ -42,14 +42,14 @@ describe('Configuration', function () {
     // need to do this with dynamic import such that the mocked config is used
     await import('../src/create-queues.js').then(({ default: createQueues }) => createQueues())
 
-    const response = await request(app).get('/meta')
+    const response = await request(app.server).get('/meta')
     expect(response.body).to.have.length(2)
 
     config.urls = []
     pubClient.publish(getRedisKey({ name: 'updateLatestVersion' }), '1234')
     await new Promise(resolve => setTimeout(resolve, 200))
 
-    const response2 = await request(app).get('/meta')
+    const response2 = await request(app.server).get('/meta')
     expect(response2.body).to.have.length(1)
   })
 })
diff --git a/integration/update-version_test.js b/integration/update-version_test.js
index c1bb9e3d0dc6e32a95600cf905f435ff5fdc7f41..cbd09e1dc0e7544ad3b5c8e870fef4aeaec12a5f 100644
--- a/integration/update-version_test.js
+++ b/integration/update-version_test.js
@@ -10,7 +10,7 @@ describe('Updates the version', function () {
 
   beforeEach(async function () {
     // need to set the redis-prefix. Otherwise, the bull workers will interfere
-    process.env.REDIS_PREFIX = Math.random()
+    process.env.REDIS_PREFIX = Math.random().toString()
     await client.flushdb()
     mockConfig({ urls: ['http://ui-server/'] })
     mockFetch({
@@ -31,7 +31,7 @@ describe('Updates the version', function () {
 
   afterEach(async function () {
     td.reset()
-    process.env.CACHE_TTL = 30000
+    process.env.CACHE_TTL = '30000'
     for (const queue of getQueues()) {
       await closeQueue(queue.name)
     }
@@ -43,7 +43,7 @@ describe('Updates the version', function () {
     // need to do this with dynamic import such that the mocked config is used
     await import('../src/create-queues.js').then(({ default: createQueues }) => createQueues())
 
-    const responseBeforeUpdate = await request(app).get('/index.html')
+    const responseBeforeUpdate = await request(app.server).get('/index.html')
     expect(responseBeforeUpdate.statusCode).to.equal(200)
     expect(responseBeforeUpdate.headers.version).to.equal('85101541')
 
@@ -52,15 +52,15 @@ describe('Updates the version', function () {
     // update is executed with the second iteration
     expect(await getQueue('update-version').add({}).then(job => job.finished())).to.equal('85102502')
 
-    const responseAfterUpdate = await request(app).get('/index.html')
+    const responseAfterUpdate = await request(app.server).get('/index.html')
     expect(responseAfterUpdate.statusCode).to.equal(200)
     expect(responseAfterUpdate.headers.version).to.equal('85102502')
   })
 
   it('with automatically triggered job', async function () {
-    process.env.CACHE_TTL = 100
+    process.env.CACHE_TTL = '100'
 
-    const responseBeforeUpdate = await request(app).get('/index.html')
+    const responseBeforeUpdate = await request(app.server).get('/index.html')
     expect(responseBeforeUpdate.statusCode).to.equal(200)
     expect(responseBeforeUpdate.headers.version).to.equal('85101541')
 
@@ -77,7 +77,7 @@ describe('Updates the version', function () {
       resolve()
     }))
 
-    const responseAfterUpdate = await request(app).get('/index.html')
+    const responseAfterUpdate = await request(app.server).get('/index.html')
     expect(responseAfterUpdate.statusCode).to.equal(200)
     expect(responseAfterUpdate.headers.version).to.equal('85102502')
   })
@@ -86,7 +86,7 @@ describe('Updates the version', function () {
     // need to do this with dynamic import such that the mocked config is used
     await import('../src/create-queues.js').then(({ default: createQueues }) => createQueues())
 
-    const responseBeforeUpdate = await request(app).get('/index.html')
+    const responseBeforeUpdate = await request(app.server).get('/index.html')
     expect(responseBeforeUpdate.statusCode).to.equal(200)
     expect(responseBeforeUpdate.headers.version).to.equal('85101541')
 
@@ -94,7 +94,7 @@ describe('Updates the version', function () {
     pubClient.publish(getRedisKey({ name: 'updateLatestVersion' }), '1234')
     await new Promise(resolve => setTimeout(resolve, 10))
 
-    const responseAfterUpdate = await request(app).get('/index.html')
+    const responseAfterUpdate = await request(app.server).get('/index.html')
     expect(responseAfterUpdate.statusCode).to.equal(200)
     expect(responseAfterUpdate.headers.version).to.equal('1234')
   })
@@ -103,7 +103,7 @@ describe('Updates the version', function () {
     beforeEach(async function () {
       td.reset()
       // need to set the redis-prefix. Otherwise, the bull workers will interfere
-      process.env.REDIS_PREFIX = Math.random()
+      process.env.REDIS_PREFIX = Math.random().toString()
       await client.flushdb()
       // preconfigure redis
       await client.set(getRedisKey({ name: 'latestVersion' }), '12345')
@@ -126,7 +126,7 @@ describe('Updates the version', function () {
     it('uses version from redis if present', async function () {
       app = await mockApp()
 
-      const response = await request(app).get('/index.html')
+      const response = await request(app.server).get('/index.html')
       expect(response.statusCode).to.equal(200)
       expect(response.headers.version).to.equal('12345')
     })
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..93b387a98b34365bd37dcad44c95953c15e0fffc
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,11 @@
+{
+  "typeAcquisition": {
+    "enable": true
+  },
+  "compilerOptions": {
+    "checkJs": true,
+    "target": "es2022",
+    "module": "es2022",
+    "moduleResolution": "node"
+  }
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 1afdc047b2f3a99b8b83469b89763e71749c9317..a6b87b7dd6181518f9994d9542fcc1190c5b96f0 100644
--- a/package.json
+++ b/package.json
@@ -18,17 +18,18 @@
   "author": "Open-Xchange",
   "license": "CC-BY-NC-SA-2.5",
   "dependencies": {
-    "@cloudnative/health-connect": "^2.1.0",
+    "@fastify/formbody": "^7.1.0",
+    "@fastify/helmet": "^9.1.0",
+    "@fastify/swagger": "^7.4.1",
     "@open-xchange/logging": "^0.0.11",
-    "@open-xchange/metrics": "^0.0.1",
     "bull": "^4.8.5",
     "dotenv-defaults": "^5.0.2",
-    "express": "^4.18.1",
-    "helmet": "^5.1.1",
+    "fastify": "^4.5.3",
+    "fastify-metrics": "^9.2.2",
+    "fastify-plugin": "^4.2.1",
     "http-errors": "^2.0.0",
     "ioredis": "^5.2.2",
-    "js-yaml": "^4.0.0",
-    "swagger-ui-express": "^4.5.0"
+    "js-yaml": "^4.0.0"
   },
   "devDependencies": {
     "autocannon": "^7.9.0",
diff --git a/spec/file-depencies_test.js b/spec/file-depencies_test.js
index b46e50521edb71aa9d08647b792b43f217fa6a36..e5bc4677ea4a7c9aec91a3efd89937c61283957b 100644
--- a/spec/file-depencies_test.js
+++ b/spec/file-depencies_test.js
@@ -38,14 +38,14 @@ describe('JS files with dependencies contain events', function () {
   })
 
   it('javascript file contains dispatcher for dependencies', async function () {
-    const response = await request(app).get('/index.html.js')
+    const response = await request(app.server).get('/index.html.js')
     expect(response.statusCode).to.equal(200)
     expect(response.headers.dependencies).to.equal('main.css')
     expect(response.text).to.equal('console.log("this is index.html.js")\n/*injected by ui-middleware*/document.dispatchEvent(new CustomEvent("load-css",{detail:{css:["main.css"]}}))')
   })
 
   it('javascript files from different versions have corrent dependencies', async function () {
-    const r1 = await request(app).get('/index.html.js')
+    const r1 = await request(app.server).get('/index.html.js')
     expect(r1.headers.dependencies).to.equal('main.css')
 
     mockFetchConfig['http://ui-server']['/manifest.json'] = generateSimpleViteManifest({
@@ -65,16 +65,16 @@ describe('JS files with dependencies contain events', function () {
       await updateVersionProcessor()
     })
 
-    const r2 = await request(app).get('/index.html.js')
+    const r2 = await request(app.server).get('/index.html.js')
     expect(r2.headers.dependencies).to.equal('other.css')
 
-    const r3 = await request(app).get('/index.html.js').set('version', r1.headers.version)
+    const r3 = await request(app.server).get('/index.html.js').set('version', r1.headers.version)
     expect(r3.headers.dependencies).to.equal('main.css')
 
-    const r4 = await request(app).get('/index.html.js').set('version', r2.headers.version)
+    const r4 = await request(app.server).get('/index.html.js').set('version', r2.headers.version)
     expect(r4.headers.dependencies).to.equal('other.css')
 
-    const r5 = await request(app).get('/index.html.js')
+    const r5 = await request(app.server).get('/index.html.js')
     expect(r5.headers.dependencies).to.equal('other.css')
   })
 })
diff --git a/spec/file_caching_test.js b/spec/file_caching_test.js
index 3bbf8f2a1e4dffd09d6d23823a7aa26b97b3ce79..229cd6fefff73a7dce871be193f94223f5a5e355 100644
--- a/spec/file_caching_test.js
+++ b/spec/file_caching_test.js
@@ -50,7 +50,7 @@ describe('File caching service', function () {
           return new Response(image, {
             headers: {
               'Content-Type': 'image/png',
-              'Content-Length': imageStat.size
+              'Content-Length': imageStat.size.toString()
             }
           })
         }
@@ -65,44 +65,44 @@ describe('File caching service', function () {
   })
 
   it('serves files defined in manifest.json file', async function () {
-    const response = await request(app).get('/example.js')
+    const response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
-    expect(response.headers['content-type']).to.equal('application/javascript; charset=utf-8')
+    expect(response.headers['content-type']).to.equal('application/javascript')
     expect(response.text).to.equal('this is example')
     // expect(response.headers['content-security-policy']).to.contain('sha256-NzZhMTE2Njc2YTgyNTZmZTdlZGVjZDU3YTNmYzRjNmM1OWZkMTI2NjRkYzZmMWM3YTkwMGU3ZTdhNDlhZmVlMwo=')
-    const response2 = await request(app).get('/test.txt')
+    const response2 = await request(app.server).get('/test.txt')
     expect(response2.statusCode).to.equal(200)
-    expect(response2.headers['content-type']).to.equal('text/plain; charset=utf-8')
+    expect(response2.headers['content-type']).to.equal('text/plain')
     expect(response2.text).to.equal('this is test')
   })
 
   it('serves css files', async function () {
-    const response = await request(app).get('/main.css')
+    const response = await request(app.server).get('/main.css')
     expect(response.statusCode).to.equal(200)
-    expect(response.headers['content-type']).to.equal('text/css; charset=utf-8')
+    expect(response.headers['content-type']).to.equal('text/css')
     // expect(response.headers['content-security-policy']).to.contain('sha256-YjRiYWRlYTVhYmM5ZTZkNjE2ZGM4YjcwZWRlNzUxMmU0YjgxY2UxMWExOTI2ZjM1NzM1M2Y2MWJjNmUwMmZjMwo=')
   })
 
   it('serves / as index.html', async function () {
-    const response = await request(app).get('/')
+    const response = await request(app.server).get('/')
     expect(response.statusCode).to.equal(200)
-    expect(response.headers['content-type']).to.equal('text/html; charset=utf-8')
+    expect(response.headers['content-type']).to.equal('text/html')
     expect(response.text).to.equal('<html><head></head><body>it\'s me</body></html>')
   })
 
   it('directly fetches files not referenced in manifest.json files from the upstream servers', async function () {
-    const response = await request(app).get('/favicon.ico')
+    const response = await request(app.server).get('/favicon.ico')
     expect(response.statusCode).to.equal(200)
     expect(response.text).to.equal('not really a favicon, though')
   })
 
   it('returns 404 if file can not be resolved', async function () {
-    const response = await request(app).get('/unknown-file.txt')
+    const response = await request(app.server).get('/unknown-file.txt')
     expect(response.statusCode).to.equal(404)
   })
 
   it('serves binary files', async function () {
-    const response = await request(app).get('/image.png')
+    const response = await request(app.server).get('/image.png')
     expect(response.statusCode).to.equal(200)
     expect(response.body.length === imageStat.size)
     expect(response.body).to.deep.equal(image)
@@ -121,10 +121,10 @@ describe('File caching service', function () {
     app = await mockApp()
 
     expect(spy.callCount).to.equal(0)
-    let response = await request(app).get('/example.js')
+    let response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy.callCount).to.equal(1)
-    response = await request(app).get('/example.js')
+    response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy.callCount).to.equal(1)
   })
@@ -142,14 +142,14 @@ describe('File caching service', function () {
     app = await mockApp()
 
     expect(spy.callCount).to.equal(0)
-    let response = await request(app).get('/example.js')
+    let response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy.callCount).to.equal(1)
     // delete file from redis
     await redis.client.del(`${response.headers.version}:/example.js:body`)
     await redis.client.del(`${response.headers.version}:/example.js:meta`)
     // and fetch once more
-    response = await request(app).get('/example.js')
+    response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy.callCount).to.equal(1)
   })
@@ -163,7 +163,7 @@ describe('File caching service', function () {
           return new Response(image, {
             headers: {
               'Content-Type': 'image/png',
-              'Content-Length': imageStat.size
+              'Content-Length': imageStat.size.toString()
             }
           })
         })
@@ -171,11 +171,11 @@ describe('File caching service', function () {
     })
     app = await mockApp()
     expect(spy.callCount).to.equal(0)
-    let response = await request(app).get('/image.png')
+    let response = await request(app.server).get('/image.png')
     expect(response.statusCode).to.equal(200)
     expect(response.body).to.deep.equal(image)
     expect(spy.callCount).to.equal(1)
-    response = await request(app).get('/image.png')
+    response = await request(app.server).get('/image.png')
     expect(response.statusCode).to.equal(200)
     expect(response.body).to.deep.equal(image)
     expect(spy.callCount).to.equal(1)
@@ -184,7 +184,7 @@ describe('File caching service', function () {
   it('a file is not cached again, if loaded from cache', async function () {
     const spy = sandbox.spy(redis.client, 'set')
 
-    let response = await request(app).get('/example.js')
+    let response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
 
     // called 4 times.
@@ -193,7 +193,7 @@ describe('File caching service', function () {
     // two times for for example.js (meta and body)
     expect(spy.callCount).to.equal(4)
 
-    response = await request(app).get('/example.js')
+    response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
 
     // should still be called 4 times, because everything is in cache
@@ -224,7 +224,7 @@ describe('File caching service', function () {
     })
     app = await mockApp()
 
-    const response = await request(app).get('/example.js')
+    const response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy1.callCount).to.equal(0)
     expect(spy2.callCount).to.equal(1)
@@ -245,25 +245,25 @@ describe('File caching service', function () {
     })
     app = await mockApp()
 
-    const response1 = await request(app).get('/example.js').set('version', 1234)
+    const response1 = await request(app.server).get('/example.js').set('version', '1234')
     expect(response1.statusCode).to.equal(200)
     expect(response1.text).to.equal('first')
 
-    const response2 = await request(app).get('/example.js')
+    const response2 = await request(app.server).get('/example.js')
     expect(response2.statusCode).to.equal(200)
     expect(response2.text).to.equal('second')
 
     const latestVersion = response2.headers['latest-version']
 
-    const response3 = await request(app).get('/example.js').set('version', 1234)
+    const response3 = await request(app.server).get('/example.js').set('version', '1234')
     expect(response3.statusCode).to.equal(200)
     expect(response3.text).to.equal('first')
 
-    const response4 = await request(app).get('/example.js')
+    const response4 = await request(app.server).get('/example.js')
     expect(response4.statusCode).to.equal(200)
     expect(response4.text).to.equal('second')
 
-    const response5 = await request(app).get('/example.js').set('version', latestVersion)
+    const response5 = await request(app.server).get('/example.js').set('version', latestVersion)
     expect(response5.statusCode).to.equal(200)
     expect(response5.text).to.equal('second')
   })
@@ -282,8 +282,8 @@ describe('File caching service', function () {
 
     expect(spy.callCount).to.equal(0)
     const [res1, res2] = await Promise.all([
-      request(app).get('/example.js'),
-      request(app).get('/example.js')
+      request(app.server).get('/example.js'),
+      request(app.server).get('/example.js')
     ])
     expect(res1.statusCode).to.equal(200)
     expect(res2.statusCode).to.equal(200)
@@ -305,8 +305,8 @@ describe('File caching service', function () {
 
     expect(spy.callCount).to.equal(0)
     const [res1, res2] = await Promise.all([
-      request(app).get('/manifests'),
-      request(app).get('/example.js')
+      request(app.server).get('/manifests'),
+      request(app.server).get('/example.js')
     ])
     expect(res1.statusCode).to.equal(200)
     expect(res2.statusCode).to.equal(200)
@@ -340,8 +340,8 @@ describe('File caching service', function () {
 
       expect(spy.callCount).to.equal(0)
       const [res1, res2] = await Promise.all([
-        request(app).get('/example.js'),
-        request(app).get('/example.js')
+        request(app.server).get('/example.js'),
+        request(app.server).get('/example.js')
       ])
       expect(res1.statusCode).to.equal(200)
       expect(res2.statusCode).to.equal(200)
@@ -350,7 +350,7 @@ describe('File caching service', function () {
   })
 
   it('serves files as gzip', async function () {
-    const response = await request(app).get('/example.js')
+    const response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(response.headers['content-encoding']).to.equal('gzip')
 
diff --git a/spec/headers_test.js b/spec/headers_test.js
index 3b6b124cbc2c27f16287cae435ecd09e6e8a9256..a1790b7be38fd729d163d9b9b5bcfe4e6e23c0b0 100644
--- a/spec/headers_test.js
+++ b/spec/headers_test.js
@@ -41,20 +41,20 @@ describe('Responses contain custom headers', function () {
   })
 
   it('index.html has version', async function () {
-    const response = await request(app).get('/index.html')
+    const response = await request(app.server).get('/index.html')
     expect(response.statusCode).to.equal(200)
     expect(response.headers.version).to.equal('3215668592')
   })
 
   it('serves requested version', async function () {
-    const response = await request(app).get('/index.html.js').set('version', '123456')
+    const response = await request(app.server).get('/index.html.js').set('version', '123456')
     expect(response.statusCode).to.equal(200)
     expect(response.headers.version).to.equal('123456')
     expect(response.headers['latest-version']).to.equal('3215668592')
   })
 
   it('javascript file contains dependencies', async function () {
-    const response = await request(app).get('/index.html.js')
+    const response = await request(app.server).get('/index.html.js')
     expect(response.statusCode).to.equal(200)
     expect(response.headers.dependencies).to.equal('main.css')
   })
@@ -78,7 +78,7 @@ describe('Responses contain custom headers', function () {
     })
 
     it('index.html has version', async function () {
-      const response = await request(app).get('/index.html')
+      const response = await request(app.server).get('/index.html')
       expect(response.statusCode).to.equal(200)
       // important here is, that it is different than in the test without meta.json
       expect(response.headers.version).to.equal('3961519424')
@@ -105,7 +105,7 @@ describe('Responses contain custom headers', function () {
     })
 
     it('index.html has version', async function () {
-      const response = await request(app).get('/index.html')
+      const response = await request(app.server).get('/index.html')
       expect(response.statusCode).to.equal(200)
       // important here is, that it is different than in the test without meta.json
       expect(response.headers.version).to.equal('1487554813')
@@ -132,7 +132,7 @@ describe('Responses contain custom headers', function () {
     })
 
     it('index.html has version', async function () {
-      const response = await request(app).get('/index.html')
+      const response = await request(app.server).get('/index.html')
       expect(response.statusCode).to.equal(200)
       // important here is, that it is different than in the test without meta.json
       expect(response.headers.version).to.equal('319344871')
diff --git a/spec/meta_test.js b/spec/meta_test.js
index de4a2a8e0f8ba958c2da4befffb0f34574b71d24..c5a0dc28046ee5e8cc2f18a15a02d99b392fc9cf 100644
--- a/spec/meta_test.js
+++ b/spec/meta_test.js
@@ -37,7 +37,7 @@ describe('Responses contain custom headers', function () {
     process.env.BUILD_TIMESTAMP = '0123456789'
     process.env.CI_COMMIT_SHA = '0123456789abcdef'
 
-    const response = await request(app).get('/meta')
+    const response = await request(app.server).get('/meta')
     expect(response.statusCode).to.equal(200)
     expect(response.body).to.deep.contain({
       id: 'ui-middleware',
@@ -49,7 +49,7 @@ describe('Responses contain custom headers', function () {
   })
 
   it('has metadata from another ui service if available', async function () {
-    const response = await request(app).get('/meta')
+    const response = await request(app.server).get('/meta')
     expect(response.statusCode).to.equal(200)
     expect(response.body).to.deep.contain({
       name: 'sample-service',
@@ -58,7 +58,7 @@ describe('Responses contain custom headers', function () {
   })
 
   it('has updated metadata if config is updated', async function () {
-    const response = await request(app).get('/meta')
+    const response = await request(app.server).get('/meta')
     expect(response.body).to.have.length(2)
 
     config.urls = []
@@ -68,7 +68,7 @@ describe('Responses contain custom headers', function () {
       await updateVersionProcessor()
     })
 
-    const response2 = await request(app).get('/meta')
+    const response2 = await request(app.server).get('/meta')
     expect(response2.body).to.have.length(1)
   })
 
@@ -79,7 +79,7 @@ describe('Responses contain custom headers', function () {
 
     it('does not have metadata from ui service when unavailable', async function () {
       await import('../src/cache.js').then(({ clear }) => clear())
-      const response = await request(app).get('/meta')
+      const response = await request(app.server).get('/meta')
       expect(response.statusCode).to.equal(200)
       expect(response.body).to.not.deep.contain({
         name: 'sample-service',
@@ -105,7 +105,7 @@ describe('Responses contain custom headers', function () {
     })
 
     it('has metadata', async function () {
-      const response = await request(app).get('/meta')
+      const response = await request(app.server).get('/meta')
       expect(response.statusCode).to.equal(200)
       expect(response.body).to.deep.contain({
         name: 'sample-service',
diff --git a/spec/redirect_test.js b/spec/redirect_test.js
index 5bf0aa7e1f44aa87f64db2851b8f07b558b9dbb5..8e8ca1cfa5c00b4fe313926d51af59b9c966fef3 100644
--- a/spec/redirect_test.js
+++ b/spec/redirect_test.js
@@ -28,19 +28,19 @@ describe('Redirects', function () {
   })
 
   it('without requested location', async function () {
-    const response = await request(app).post('/redirect')
+    const response = await request(app.server).post('/redirect')
     expect(response.statusCode).to.equal(302)
     expect(response.headers.location).to.equal('../busy.html')
   })
 
   it('with requested location', async function () {
-    const response = await request(app).post('/redirect').send('location=/appsuite/whatever/path')
+    const response = await request(app.server).post('/redirect').send('location=/appsuite/whatever/path')
     expect(response.statusCode).to.equal(302)
     expect(response.headers.location).to.equal('/appsuite/whatever/path')
   })
 
   it('redirects /ui to /', async function () {
-    const response = await request(app).get('/ui')
+    const response = await request(app.server).get('/ui')
     expect(response.statusCode).to.equal(302)
     expect(response.headers.location).to.equal('/')
   })
diff --git a/spec/redis_test.js b/spec/redis_test.js
index 26da95c55a36e45716e6a07517c5b9ac29988204..b1d2e46f4784b3f7775e884a27c779a2e7487a44 100644
--- a/spec/redis_test.js
+++ b/spec/redis_test.js
@@ -31,10 +31,10 @@ describe('Redis', function () {
 
   it('use internal cache, when redis is disabled', async function () {
     expect(spy.callCount).to.equal(0)
-    let response = await request(app).get('/example.js')
+    let response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy.callCount).to.equal(1)
-    response = await request(app).get('/example.js')
+    response = await request(app.server).get('/example.js')
     expect(response.statusCode).to.equal(200)
     expect(spy.callCount).to.equal(1)
   })
diff --git a/spec/server_test.js b/spec/server_test.js
index b1d3c547e2fbae3a7eeb3dbaf9dc70d35c0f7b09..a2e0fc3405ac4d2ad9592e2876b65c3236cba247 100644
--- a/spec/server_test.js
+++ b/spec/server_test.js
@@ -23,19 +23,24 @@ describe('UI Middleware', function () {
   afterEach(async function () {
     td.reset()
     await new RedisMock().flushdb()
-    process.env.CACHE_TTL = 30000
+    process.env.CACHE_TTL = '30000'
   })
 
   // Some say, this is not necessary to test
   // But failing startups due to code errors in the probes will cause this to not work
   // Therefore, we should keep this
-  it('is healthy', async function () {
-    const response = await request(app).get('/healthy')
+  it('is ready', async function () {
+    const response = await request(app.server).get('/ready')
+    expect(response.statusCode).to.equal(200)
+  })
+
+  it('is live', async function () {
+    const response = await request(app.server).get('/live')
     expect(response.statusCode).to.equal(200)
   })
 
   it('fetches manifest data', async function () {
-    const response = await request(app).get('/manifests')
+    const response = await request(app.server).get('/manifests')
     expect(response.statusCode).to.equal(200)
     expect(response.body).to.deep.equal([{ namespace: 'test', path: 'example' }])
   })
@@ -51,7 +56,7 @@ describe('UI Middleware', function () {
     })
 
     it('caches manifest data', async function () {
-      const response = await request(app).get('/manifests')
+      const response = await request(app.server).get('/manifests')
       expect(response.statusCode).to.equal(200)
       expect(response.body).to.deep.equal([{ namespace: 'test', path: 'example' }])
 
@@ -62,7 +67,7 @@ describe('UI Middleware', function () {
 
       await new Promise(resolve => setTimeout(resolve, 150))
 
-      const response2 = await request(app).get('/manifests')
+      const response2 = await request(app.server).get('/manifests')
       expect(response2.statusCode).to.equal(200)
       expect(response2.body).to.deep.equal([{ namespace: 'test', path: 'example' }])
     })
@@ -86,7 +91,7 @@ describe('UI Middleware', function () {
     })
 
     it('can load multiple configurations', async function () {
-      await request(app)
+      await request(app.server)
         .get('/manifests')
         .then(response => {
           expect(response.statusCode).to.equal(200)
diff --git a/spec/util.js b/spec/util.js
index 78d34a7bbe59eb975d71bc4200a0a48a5ec8d406..f900351523b933452a8116a3cc0dd6ae272b0dad 100644
--- a/spec/util.js
+++ b/spec/util.js
@@ -45,7 +45,7 @@ export function mockRedis (data = {}, isEnabled = true) {
   const mock = {
     isReady () { return Promise.resolve() },
     isEnabled () { return isEnabled },
-    client: new RedisMock({ data }),
+    client: new RedisMock(data),
     pubClient: new RedisMock(),
     subClient: new RedisMock()
   }
@@ -56,7 +56,8 @@ export function mockRedis (data = {}, isEnabled = true) {
 export async function mockApp () {
   register.clear()
   const { createApp } = await import('../src/create-app.js')
-  const app = createApp()
-  await request(app).get('/ready')
+  const app = await createApp()
+  app.listen({ port: 0 })
+  await request(app.server).get('/ready')
   return app
 }
diff --git a/src/config.js b/src/config.js
index 233c19c4f6669922cbd655184cd108cee6b93a42..4dd7aff4518d9fc75868daddc09ebf3266932d2b 100644
--- a/src/config.js
+++ b/src/config.js
@@ -4,8 +4,9 @@ import { logger } from './logger.js'
 
 class Config {
   async load () {
-    const urlsSource = await fs.readFile('./config/config.yaml', 'utf8')
-    this._urls = yaml.load(urlsSource).baseUrls
+    const doc = yaml.load(await fs.readFile('./config/config.yaml', 'utf8'))
+    // @ts-ignore
+    this._urls = doc.baseUrls
     logger.debug('[Config] Config has been loaded')
   }
 
diff --git a/src/create-app.js b/src/create-app.js
index 10b21bff537aaa769154d83fec112b96101e490b..b65a6d10de0fee4fd5f754b884991ed99b4be11c 100644
--- a/src/create-app.js
+++ b/src/create-app.js
@@ -1,50 +1,53 @@
-import express from 'express'
-import helmet from 'helmet'
-import { httpLogger } from './logger.js'
-import { metricsMiddleware } from '@open-xchange/metrics'
-import swaggerUi from 'swagger-ui-express'
+import fastify from 'fastify'
+import formBodyPlugin from '@fastify/formbody'
+import fastifySwagger from '@fastify/swagger'
+import fastifyMetrics from 'fastify-metrics'
+import helmet from '@fastify/helmet'
 import yaml from 'js-yaml'
 import fs from 'fs'
 
-import versionMiddleware from './middlewares/version.js'
-import serveFilesMiddleware from './middlewares/serve-files.js'
-import finalHandlerMiddleware from './middlewares/final-handler.js'
-
-import health from './routes/health.js'
-import manifestsRouter from './routes/manifests.js'
-import metadataRouter from './routes/metadata.js'
-import redirectsRouter from './routes/redirects.js'
+import versionHandler from './handlers/version.js'
+import healthPlugin from './plugins/health.js'
+import manifestsPlugin from './plugins/manifests.js'
+import metadataPlugin from './plugins/metadata.js'
+import redirectsPlugin from './plugins/redirects.js'
+import serveFilePlugin from './plugins/serve-files.js'
+import { logger } from './logger.js'
 
 const swaggerDocument = yaml.load(fs.readFileSync('./src/swagger.yaml', 'utf8'))
 
-const metricsMiddlewareInstance = metricsMiddleware()
-
-export function createApp () {
-  const app = express()
-  app.use(express.urlencoded({ extended: true }))
-
-  // Application-level middleware
-  app.use(httpLogger)
-  app.use(helmet({
+export async function createApp (basePath) {
+  const app = fastify({
+    logger,
+    connectionTimeout: 30000
+  })
+  await app.register(formBodyPlugin)
+  await app.register(helmet, {
     contentSecurityPolicy: false,
     crossOriginEmbedderPolicy: false,
     originAgentCluster: false,
     crossOriginOpenerPolicy: { policy: 'same-origin-allow-popups' }
-  }))
-  app.use(health)
-  app.use(metricsMiddlewareInstance)
-  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
-  app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
-  app.timeout = 30000
-
-  app.use(versionMiddleware)
-
-  app.use(manifestsRouter)
-  app.use(metadataRouter)
-  app.use(redirectsRouter)
-
-  app.use(serveFilesMiddleware)
-  app.use(finalHandlerMiddleware)
+  })
+  await app.register(healthPlugin)
+  await app.register(fastifyMetrics, {
+    routeMetrics: {
+      routeBlacklist: ['/ready', '/live', '/health', '/healthy', '/metrics', '/api-docs']
+    }
+  })
+  await app.register(fastifySwagger, {
+    routePrefix: '/api-docs',
+    prefix: process.env.APP_ROOT,
+    swagger: swaggerDocument,
+    exposeRoute: process.env.EXPOSE_API_DOCS === 'true'
+  })
+
+  await app.addHook('preHandler', versionHandler)
+
+  await app.register(manifestsPlugin, { prefix: process.env.APP_ROOT })
+  await app.register(metadataPlugin, { prefix: process.env.APP_ROOT })
+  await app.register(redirectsPlugin, { prefix: process.env.APP_ROOT })
+
+  await app.register(serveFilePlugin, { prefix: process.env.APP_ROOT })
 
   return app
 }
diff --git a/src/handlers/version.js b/src/handlers/version.js
new file mode 100644
index 0000000000000000000000000000000000000000..d02e90fee188b0403da660dd707a2727d0bb658d
--- /dev/null
+++ b/src/handlers/version.js
@@ -0,0 +1,9 @@
+import { getLatestVersion } from '../version.js'
+
+export default async function versionHandler (req, reply) {
+  const latestVersion = await getLatestVersion()
+  const version = req.headers.version || latestVersion
+  reply.header('version', version)
+  reply.header('latest-version', latestVersion)
+  reply.version = version
+}
diff --git a/src/index.js b/src/index.js
index a6ef6d48501eca452b25353ddf82ba4780770783..992a191719bf34ed0e3b4de07470f7ed6326c461 100644
--- a/src/index.js
+++ b/src/index.js
@@ -3,18 +3,14 @@
 import { config } from 'dotenv-defaults'
 import { logger } from './logger.js'
 import { createApp } from './create-app.js'
-import express from 'express'
 import createQueues from './create-queues.js'
 config()
 
-const root = express()
-const app = createApp()
+const app = await createApp()
 createQueues()
 
 // Binds and listens for connections on the specified host and port
-root.listen(process.env.PORT, () => {
-  logger.info(`[Server] ui-middleware listening on port ${process.env.PORT}, PID: ${process.pid}`)
-})
+app.listen({ host: '::', port: Number(process.env.PORT) })
 
 process.on('uncaughtException', err => {
   logger.error(err, 'uncaughtException')
@@ -25,5 +21,3 @@ process.on('unhandledRejection', err => {
   logger.error(err, 'unhandledRejection')
   process.exit(1)
 })
-
-root.use(process.env.APP_ROOT, app)
diff --git a/src/logger.js b/src/logger.js
index 50b37a87f50778a4191be0441439a003b28b67c0..e702c2b09f453521a0a98551f02f31d0a62627ef 100644
--- a/src/logger.js
+++ b/src/logger.js
@@ -1,8 +1,8 @@
 import { config } from 'dotenv-defaults'
-import { createLogger, createHttpLogger } from '@open-xchange/logging'
+import { createLogger } from '@open-xchange/logging'
+
 config()
 
-export const httpLogger = createHttpLogger()
 export const logger = createLogger()
-export const t0 = +new Date()
-export const timeSinceStartup = () => (new Date() - t0) / 1000
+export const t0 = Date.now()
+export const timeSinceStartup = () => (Date.now() - t0) / 1000
diff --git a/src/middlewares/final-handler.js b/src/middlewares/final-handler.js
deleted file mode 100644
index 826a35b3e6aa81429deab49163fe5d099b52a20e..0000000000000000000000000000000000000000
--- a/src/middlewares/final-handler.js
+++ /dev/null
@@ -1,18 +0,0 @@
-import createError from 'http-errors'
-import path from 'path'
-import { logger } from '../logger.js'
-
-export default [function (req, res, next) {
-  const { body, headers } = res
-  if (!body) return next(createError(404, 'File does not exist.'))
-
-  res.type(headers?.['content-type'] || path.extname(req.path) || 'html')
-  if (headers) res.set(headers)
-
-  res.status(200).send(body)
-}, function (err, req, res, next) {
-  if (!err) next()
-  if (err.status >= 400 && err.status < 500) logger.warn(err)
-  else logger.error(err)
-  res.status(err.status || 500).send(err.message || 'Internal server error occured')
-}]
diff --git a/src/middlewares/serve-files.js b/src/middlewares/serve-files.js
deleted file mode 100644
index 4bae7331d8c031a5681ce367f71ecf1baf5f798b..0000000000000000000000000000000000000000
--- a/src/middlewares/serve-files.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { getFile } from '../files.js'
-import { NotFoundError } from '../errors.js'
-import createError from 'http-errors'
-
-export default async function (req, res, next) {
-  try {
-    if (req.method !== 'GET') return next()
-    const version = res.version
-    const path = req.path === '/' ? '/index.html' : req.path
-    const { body, headers } = await getFile({ version, path })
-
-    res.set(headers)
-    res.send(body)
-  } catch (err) {
-    const errors = err.errors || [err]
-    const fileNotFound = errors.reduce((memo, error) => memo && error instanceof NotFoundError, true)
-    if (fileNotFound) next(createError(404, 'File does not exist.'))
-    else next(err)
-  }
-}
diff --git a/src/middlewares/version.js b/src/middlewares/version.js
deleted file mode 100644
index f62ecbc14a45c7dc84f35ec72a5297040b606936..0000000000000000000000000000000000000000
--- a/src/middlewares/version.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { getLatestVersion } from '../version.js'
-
-export default async (req, res, next) => {
-  try {
-    const latestVersion = await getLatestVersion()
-    const version = req.get('version') || latestVersion
-    res.setHeader('version', version)
-    res.setHeader('latest-version', latestVersion)
-    res.version = version
-  } catch (err) {
-    next(err)
-  } finally {
-    next()
-  }
-}
diff --git a/src/plugins/health.js b/src/plugins/health.js
new file mode 100644
index 0000000000000000000000000000000000000000..181c3d6b2b0dc590c57a49790ef7c94f7b7a2b85
--- /dev/null
+++ b/src/plugins/health.js
@@ -0,0 +1,47 @@
+import * as redis from '../redis.js'
+import { getLatestVersion } from '../version.js'
+import { once } from '../util.js'
+import { config } from '../config.js'
+import { logger, timeSinceStartup } from '../logger.js'
+import createError from 'http-errors'
+
+const checkRedis = () => {
+  if (redis.isEnabled()) {
+    return redis.isReady()
+  }
+}
+
+const checkLatestVersion = once(async function () {
+  // config is required before the first version check
+  await config.load()
+  await getLatestVersion()
+  logger.info(`[Health] Check latest version on startup. Time since startup: ${timeSinceStartup()}`)
+})
+
+async function live () {}
+
+async function ready () {
+  await Promise.all([
+    checkLatestVersion(),
+    checkRedis()
+  ])
+}
+
+export default async function healthPlugin (fastify, options) {
+  fastify.decorate('probe', async (reply, func) => {
+    try {
+      await func()
+      reply.send('')
+    } catch (err) {
+      throw createError(503)
+    }
+  })
+
+  fastify.get('/live', async (req, reply) => {
+    await fastify.probe(reply, live)
+  })
+
+  fastify.get('/ready', async (req, reply) => {
+    await fastify.probe(reply, ready)
+  })
+}
diff --git a/src/plugins/manifests.js b/src/plugins/manifests.js
new file mode 100644
index 0000000000000000000000000000000000000000..0f074c1394f60557bcce9eabba1a508cd41fe0c1
--- /dev/null
+++ b/src/plugins/manifests.js
@@ -0,0 +1,8 @@
+import { getOxManifests } from '../manifests.js'
+
+export default async function manifestsPlugin (fastify, options) {
+  fastify.get('/manifests', async (req, res) => {
+    if (res.body) return
+    res.send(await getOxManifests({ version: res.version }))
+  })
+}
diff --git a/src/plugins/metadata.js b/src/plugins/metadata.js
new file mode 100644
index 0000000000000000000000000000000000000000..81917880dde1b1fc54bdc211a0d7102e24ea964a
--- /dev/null
+++ b/src/plugins/metadata.js
@@ -0,0 +1,7 @@
+import { getMergedMetadata } from '../meta.js'
+
+export default async function metadataPlugin (fastify, options) {
+  fastify.get('/meta', async (req, res) => {
+    res.send(await getMergedMetadata({ version: res.version }))
+  })
+}
diff --git a/src/plugins/redirects.js b/src/plugins/redirects.js
new file mode 100644
index 0000000000000000000000000000000000000000..d057a2b19b6a82921c5b17cf2e4b5e02eb4fbf9a
--- /dev/null
+++ b/src/plugins/redirects.js
@@ -0,0 +1,10 @@
+export default async function redirectsPlugin (fastify, options) {
+  fastify.get('/ui', async (req, res) => {
+    res.redirect(process.env.APP_ROOT)
+  })
+
+  fastify.post('/redirect', async (req, res) => {
+    const location = req.body?.location || '../busy.html'
+    res.redirect(location)
+  })
+}
diff --git a/src/plugins/serve-files.js b/src/plugins/serve-files.js
new file mode 100644
index 0000000000000000000000000000000000000000..f6b9cb933ce416caf0c6f830c431ab5d6bc52e62
--- /dev/null
+++ b/src/plugins/serve-files.js
@@ -0,0 +1,24 @@
+import { getFile } from '../files.js'
+import { NotFoundError } from '../errors.js'
+import createError from 'http-errors'
+
+export default async function serveFilePlugin (fastify, options) {
+  fastify.get('*', async (req, reply) => {
+    try {
+      const version = reply.version
+      const url = req.url.substr((options.prefix || '/').length - 1)
+      const path = url === '/' ? '/index.html' : url
+      const { body, headers } = await getFile({ version, path })
+
+      Object.entries(headers).forEach(([key, value]) => {
+        reply.header(key, value)
+      })
+      reply.send(body)
+    } catch (err) {
+      const errors = err.errors || [err]
+      const fileNotFound = errors.reduce((memo, error) => memo && error instanceof NotFoundError, true)
+      if (fileNotFound) throw createError(404, 'File does not exist.')
+      throw err
+    }
+  })
+}
diff --git a/src/redis.js b/src/redis.js
index 1e5e2abd497e87ffb6052c63862f6295a9c30469..a26432a97be863c7e37444cd035b0c578842b69c 100644
--- a/src/redis.js
+++ b/src/redis.js
@@ -6,7 +6,16 @@ const commonQueueOptions = { enableReadyCheck: false, maxRetriesPerRequest: null
 
 const createClient = (type, options = {}) => {
   if (!isEnabled()) {
-    return new Proxy({}, {
+    return new Proxy({
+      getBuffer () {},
+      get () {},
+      set () {},
+      del () {},
+      flushdb () {},
+      status: '',
+      duplicate () { return new Redis() },
+      publish () {}
+    }, {
       get () {
         throw new Error('Redis is disabled. Check for redis.isEnabled()')
       }
@@ -15,8 +24,8 @@ const createClient = (type, options = {}) => {
 
   const client = new Redis({
     host: process.env.REDIS_HOST,
-    port: process.env.REDIS_PORT || 6379,
-    db: process.env.REDIS_DB,
+    port: Number(process.env.REDIS_PORT),
+    db: Number(process.env.REDIS_DB),
     password: process.env.REDIS_PASSWORD,
     ...options
   })
@@ -43,12 +52,13 @@ const queues = {}
 
 export function getQueue (name) {
   if (queues[name]) return queues[name]
+  // @ts-ignore
   return (queues[name] = new Queue(name, {
     prefix: process.env.REDIS_PREFIX,
     createClient: function (type) {
       switch (type) {
         case 'client':
-          return client
+          return client.duplicate()
         case 'subscriber':
           return subClient.duplicate()
         default:
diff --git a/src/routes/health.js b/src/routes/health.js
deleted file mode 100644
index 6920cd0624596e30cdeb6f429f9857e52c5dbe6e..0000000000000000000000000000000000000000
--- a/src/routes/health.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import { Router } from 'express'
-import health from '@cloudnative/health-connect'
-import * as redis from '../redis.js'
-import { getLatestVersion } from '../version.js'
-import { once } from '../util.js'
-import { config } from '../config.js'
-import { logger, timeSinceStartup } from '../logger.js'
-const router = Router()
-const healthCheck = new health.HealthChecker()
-
-if (redis.isEnabled()) {
-  const redisReady = new health.ReadinessCheck('Redis ready', redis.isReady)
-  healthCheck.registerReadinessCheck(redisReady)
-}
-
-const checkLatestVersion = new health.StartupCheck('check latest version', once(async function () {
-  // config is required before the first version check
-  await config.load()
-  await getLatestVersion()
-  logger.info(`[Health] Check latest version on startup. Time since startup: ${timeSinceStartup()}`)
-}))
-
-healthCheck.registerStartupCheck(checkLatestVersion)
-
-router.use('/live', health.LivenessEndpoint(healthCheck))
-router.use('/ready', health.ReadinessEndpoint(healthCheck))
-router.use('/healthy', health.HealthEndpoint(healthCheck))
-
-export default router
diff --git a/src/routes/manifests.js b/src/routes/manifests.js
deleted file mode 100644
index 5d75dd2bbf4ac6a019d766c8dcb6f8ad72be8609..0000000000000000000000000000000000000000
--- a/src/routes/manifests.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { Router } from 'express'
-import { getOxManifests } from '../manifests.js'
-
-const router = new Router()
-
-router.get('/manifests', async function (req, res, next) {
-  try {
-    if (res.body) return
-    res.send(await getOxManifests({ version: res.version }))
-  } catch (err) {
-    next(err)
-  }
-})
-
-export default router
diff --git a/src/routes/metadata.js b/src/routes/metadata.js
deleted file mode 100644
index ebe28e7628bc47308d93ed9f05c87774db3bf9b3..0000000000000000000000000000000000000000
--- a/src/routes/metadata.js
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Router } from 'express'
-import { getMergedMetadata } from '../meta.js'
-
-const router = new Router()
-
-router.get('/meta', async (req, res, next) => {
-  try {
-    res.send(await getMergedMetadata({ version: res.version }))
-  } catch (err) {
-    next(err)
-  }
-})
-
-export default router
diff --git a/src/routes/redirects.js b/src/routes/redirects.js
deleted file mode 100644
index 8c73035451153efe7c26525cc4b006250e8ab793..0000000000000000000000000000000000000000
--- a/src/routes/redirects.js
+++ /dev/null
@@ -1,17 +0,0 @@
-import { Router } from 'express'
-
-const router = new Router()
-
-// backwards compatibility for 7.10.x
-// this should hopefully be resolved with an ingress
-// or proper config. But is used to be safe on all ends
-router.get('/ui', async (req, res, next) => {
-  res.redirect(process.env.APP_ROOT)
-})
-
-router.post('/redirect', (req, res, next) => {
-  const location = req.body.location || '../busy.html'
-  res.redirect(location)
-})
-
-export default router
diff --git a/src/util.js b/src/util.js
index c9eccb5cfb80a385051185f0c9c324ff42f4771b..1691bed8546cdb1680301fc4a1191f878ebcb964 100644
--- a/src/util.js
+++ b/src/util.js
@@ -55,7 +55,7 @@ export function viteToOxManifest (viteManifests) {
     .flat()
 }
 
-export function getRedisKey ({ version, name }) {
+export function getRedisKey ({ version = undefined, name }) {
   if (version && name) return `${process.env.REDIS_PREFIX}:${version}:${name}`
   return `${process.env.REDIS_PREFIX}:${name}`
 }
@@ -71,4 +71,4 @@ export function once (fn, context) {
     return res
   }
 }
-export const t0 = +new Date()
+export const t0 = Date.now()
diff --git a/src/version.js b/src/version.js
index 87c7eb71a2a624bdd58a13da197a3296d47eb61f..9c500ebea7098ddd26d8242f13473039f582e8c8 100644
--- a/src/version.js
+++ b/src/version.js
@@ -40,6 +40,7 @@ export async function getLatestVersion () {
     }
   }
 
+  await config.load()
   const version = await fetchLatestVersion()
   logger.info(`[Version] Fetched initial version: '${version}'`)
 
diff --git a/yarn.lock b/yarn.lock
index 74d215a8861677cb2a04f46335fe8c77859a24a5..9dd7cb3c421c61ce1c632def5e1a21cac989c323 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7,18 +7,6 @@
   resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.19.23.tgz#7fccae28d0a2692869f1d1219d36093bc24d5e72"
   integrity sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==
 
-"@cloudnative/health-connect@^2.1.0":
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/@cloudnative/health-connect/-/health-connect-2.1.0.tgz#f6cc0d4d2ba5c7e91b7b53c28ce0ca48eb9cc1cd"
-  integrity sha512-GieeiusY64i1Q5LdAf70n5W08MF5uom3qdVvnwIed/asBqpNPv7hlC6FGSH20lTYvyujF3wV5oBDcTa4SS/cbA==
-  dependencies:
-    "@cloudnative/health" "^2.1.1"
-
-"@cloudnative/health@^2.1.1":
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/@cloudnative/health/-/health-2.1.2.tgz#337a4d23ac6872ec439e21aec2499785d7a27fd4"
-  integrity sha512-mEQdbj9dM4KMClS358MCzbqXUmj+Vw5snjDb5bXdaf1sZvVu7+3UqR4HaG4RoNkNUwe1yjfIuengdyWp9quF1A==
-
 "@colors/colors@1.5.0":
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
@@ -39,6 +27,77 @@
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
+"@fastify/accept-negotiator@^1.0.0":
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/@fastify/accept-negotiator/-/accept-negotiator-1.0.0.tgz#f0e73a3f8c6ba739d66a629b386c838889ec7a23"
+  integrity sha512-4R/N2KfYeld7A5LGkai+iUFMahXcxxYbDp+XS2B1yuL3cdmZLJ9TlCnNzT3q5xFTqsYm0GPpinLUwfSwjcVjyA==
+
+"@fastify/ajv-compiler@^3.1.1":
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/@fastify/ajv-compiler/-/ajv-compiler-3.2.0.tgz#a165ffb877fe239571a68f7b22143034176dcb8a"
+  integrity sha512-JrqgKmZoh1AJojDZk699DupQ9+tz5gSy7/w+5DrkXy5whM5IcqdV3SjG5qnOqgVJT1nPtUMDY0xYus2j6vwJiw==
+  dependencies:
+    ajv "^8.10.0"
+    ajv-formats "^2.1.1"
+    fast-uri "^2.0.0"
+
+"@fastify/deepmerge@^1.0.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@fastify/deepmerge/-/deepmerge-1.1.0.tgz#91f0a5a27034ff76b7bece63a5906894940ace82"
+  integrity sha512-E8Hfdvs1bG6u0N4vN5Nty6JONUfTdOciyD5rn8KnEsLKIenvOVcr210BQR9t34PRkNyjqnMLGk3e0BsaxRdL+g==
+
+"@fastify/error@^3.0.0":
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/@fastify/error/-/error-3.0.0.tgz#bfcb7b33cec0196413083a91ef2edc7b2c88455b"
+  integrity sha512-dPRyT40GiHRzSCll3/Jn2nPe25+E1VXc9tDwRAIKwFCxd5Np5wzgz1tmooWG3sV0qKgrBibihVoCna2ru4SEFg==
+
+"@fastify/fast-json-stringify-compiler@^4.0.0":
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/@fastify/fast-json-stringify-compiler/-/fast-json-stringify-compiler-4.1.0.tgz#ebf657ce4ec88e27ba311f7560eaa0b37de8719d"
+  integrity sha512-cTKBV2J9+u6VaKDhX7HepSfPSzw+F+TSd+k0wzifj4rG+4E5PjSFJCk19P8R6tr/72cuzgGd+mbB3jFT6lvAgw==
+  dependencies:
+    fast-json-stringify "^5.0.0"
+
+"@fastify/formbody@^7.1.0":
+  version "7.1.0"
+  resolved "https://registry.yarnpkg.com/@fastify/formbody/-/formbody-7.1.0.tgz#be1963dc439483b5d49f14853243bdf87e7a3e3a"
+  integrity sha512-jiMb1Ie7APs7mLBuLeBGoMD0mhMGuQECjBhhPYxoFcPaORD10Ocjxwg2BWTkBgg1PYxJWXkVxFxoyBLXGrJDdA==
+  dependencies:
+    fastify-plugin "^4.0.0"
+
+"@fastify/helmet@^9.1.0":
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/@fastify/helmet/-/helmet-9.1.0.tgz#6a87b35c8d03a826ee052e306d2d2c81b49088bc"
+  integrity sha512-wAtu/38t90vH46GdLM6pVi8tM1HZXb6PRdLTNBo9pudSfSw5i5Ogm8Hq1Nx337WjgSOeU6MefaTd+1avlOlCDQ==
+  dependencies:
+    fastify-plugin "^3.0.0"
+    helmet "^5.0.1"
+
+"@fastify/static@^6.0.0":
+  version "6.5.0"
+  resolved "https://registry.yarnpkg.com/@fastify/static/-/static-6.5.0.tgz#004fdb487ddf0ee5fdf7541e56bfcb493d7a1060"
+  integrity sha512-WEk6iqgejA6ivjkvbJ47A+uMci225z5lZwLXCXZS3ZYR/kYje1gzzarkKKGL6TWpBw6smkOzxA7dfEoY0347Nw==
+  dependencies:
+    "@fastify/accept-negotiator" "^1.0.0"
+    content-disposition "^0.5.3"
+    fastify-plugin "^4.0.0"
+    glob "^8.0.1"
+    p-limit "^3.1.0"
+    readable-stream "^4.0.0"
+    send "^0.18.0"
+
+"@fastify/swagger@^7.4.1":
+  version "7.4.1"
+  resolved "https://registry.yarnpkg.com/@fastify/swagger/-/swagger-7.4.1.tgz#7149a5db69f03a7d43b74ba891fda8ce35d761a0"
+  integrity sha512-SN3sjz4dsb6jyochD6RNXG1GYBmt45YCIiQW3YjXF1Q8hP4aYQ7pVcRH2prcm12G6MJ4fGq58ywqh3prrO/Ocg==
+  dependencies:
+    "@fastify/static" "^6.0.0"
+    fastify-plugin "^3.0.1"
+    js-yaml "^4.1.0"
+    json-schema-resolver "^1.3.0"
+    openapi-types "^11.0.0"
+    rfdc "^1.3.0"
+
 "@humanwhocodes/config-array@^0.10.4":
   version "0.10.4"
   resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c"
@@ -128,14 +187,6 @@
     pino-http "^6.5.0"
     pino-pretty "^7.4.0"
 
-"@open-xchange/metrics@^0.0.1":
-  version "0.0.1"
-  resolved "https://registry.yarnpkg.com/@open-xchange/metrics/-/metrics-0.0.1.tgz#2531f053137077e1c89ad1fc42d3ed59df68f2ff"
-  integrity sha512-Z2gH3USWzXDvZwxhecfZOOT1Ixse7n1aiq1Q87pFAQAyGVZeUJOIgIeCpU2m39SXFlI0Z2hwepa6Eapa+Ujj8g==
-  dependencies:
-    express-prom-bundle "^6.4.1"
-    prom-client "^14.0.1"
-
 "@sinonjs/commons@^1.6.0", "@sinonjs/commons@^1.7.0", "@sinonjs/commons@^1.8.3":
   version "1.8.3"
   resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
@@ -179,13 +230,17 @@ abbrev@1:
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
   integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
 
-accepts@~1.3.8:
-  version "1.3.8"
-  resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
-  integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+abort-controller@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
+  integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
   dependencies:
-    mime-types "~2.1.34"
-    negotiator "0.6.3"
+    event-target-shim "^5.0.0"
+
+abstract-logging@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
+  integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
 
 acorn-jsx@^5.3.2:
   version "5.3.2"
@@ -205,6 +260,13 @@ aggregate-error@^3.0.0:
     clean-stack "^2.0.0"
     indent-string "^4.0.0"
 
+ajv-formats@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+  integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+  dependencies:
+    ajv "^8.0.0"
+
 ajv@^6.10.0, ajv@^6.12.4:
   version "6.12.6"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
@@ -215,6 +277,16 @@ ajv@^6.10.0, ajv@^6.12.4:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
+ajv@^8.0.0, ajv@^8.10.0:
+  version "8.11.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
+  integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    json-schema-traverse "^1.0.0"
+    require-from-string "^2.0.2"
+    uri-js "^4.2.2"
+
 ansi-colors@4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
@@ -264,6 +336,11 @@ anymatch@~3.1.2:
     normalize-path "^3.0.0"
     picomatch "^2.0.4"
 
+archy@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
+  integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==
+
 argparse@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
@@ -279,11 +356,6 @@ args@^5.0.1:
     leven "2.1.0"
     mri "1.1.4"
 
-array-flatten@1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
-  integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
-
 array-includes@^3.1.4:
   version "3.1.5"
   resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb"
@@ -364,6 +436,15 @@ autocannon@^7.9.0:
     subarg "^1.0.0"
     timestring "^6.0.0"
 
+avvio@^8.1.3:
+  version "8.2.0"
+  resolved "https://registry.yarnpkg.com/avvio/-/avvio-8.2.0.tgz#aff28b0266617bf07ffc1c2d5f4220c3663ce1c2"
+  integrity sha512-bbCQdg7bpEv6kGH41RO/3B2/GMMmJSo2iBK+X8AWN9mujtfUipMDfIjsgHCfpnKqoGEQrrmCDKSa5OQ19+fDmg==
+  dependencies:
+    archy "^1.0.0"
+    debug "^4.0.0"
+    fastq "^1.6.1"
+
 balanced-match@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@@ -384,24 +465,6 @@ bintrees@1.0.2:
   resolved "https://registry.yarnpkg.com/bintrees/-/bintrees-1.0.2.tgz#49f896d6e858a4a499df85c38fb399b9aff840f8"
   integrity sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==
 
-body-parser@1.20.0:
-  version "1.20.0"
-  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
-  integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
-  dependencies:
-    bytes "3.1.2"
-    content-type "~1.0.4"
-    debug "2.6.9"
-    depd "2.0.0"
-    destroy "1.2.0"
-    http-errors "2.0.0"
-    iconv-lite "0.4.24"
-    on-finished "2.4.1"
-    qs "6.10.3"
-    raw-body "2.5.1"
-    type-is "~1.6.18"
-    unpipe "1.0.0"
-
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -451,11 +514,6 @@ bull@^4.8.5:
     semver "^7.3.2"
     uuid "^8.3.0"
 
-bytes@3.1.2:
-  version "3.1.2"
-  resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
-  integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
-
 call-bind@^1.0.0, call-bind@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@@ -641,24 +699,14 @@ concat-map@0.0.1:
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
   integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
 
-content-disposition@0.5.4:
+content-disposition@^0.5.3:
   version "0.5.4"
   resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
   integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
   dependencies:
     safe-buffer "5.2.1"
 
-content-type@~1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
-  integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
-
-cookie-signature@1.0.6:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
-  integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
-
-cookie@0.5.0:
+cookie@^0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
   integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
@@ -701,7 +749,7 @@ debug@2.6.9, debug@^2.6.9:
   dependencies:
     ms "2.0.0"
 
-debug@4.3.4, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+debug@4.3.4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
   version "4.3.4"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
   integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -1122,6 +1170,11 @@ etag@~1.8.1:
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
   integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
 
+event-target-shim@^5.0.0:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
+  integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
+
 execa@^6.1.0:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/execa/-/execa-6.1.0.tgz#cea16dee211ff011246556388effa0818394fb20"
@@ -1137,51 +1190,6 @@ execa@^6.1.0:
     signal-exit "^3.0.7"
     strip-final-newline "^3.0.0"
 
-express-prom-bundle@^6.4.1:
-  version "6.5.0"
-  resolved "https://registry.yarnpkg.com/express-prom-bundle/-/express-prom-bundle-6.5.0.tgz#cdf28b29907618cae933ed14d5b727f7404e810b"
-  integrity sha512-paFAm0FK7TV1Ln6Blh9edDt2mJ4Pk6Py/fjhZDMcoMHENYryBjCpnXDXuCu8NE1kkvp58IrPcAAkNeNqdvZnnw==
-  dependencies:
-    on-finished "^2.3.0"
-    url-value-parser "^2.0.0"
-
-express@^4.18.1:
-  version "4.18.1"
-  resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
-  integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
-  dependencies:
-    accepts "~1.3.8"
-    array-flatten "1.1.1"
-    body-parser "1.20.0"
-    content-disposition "0.5.4"
-    content-type "~1.0.4"
-    cookie "0.5.0"
-    cookie-signature "1.0.6"
-    debug "2.6.9"
-    depd "2.0.0"
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    etag "~1.8.1"
-    finalhandler "1.2.0"
-    fresh "0.5.2"
-    http-errors "2.0.0"
-    merge-descriptors "1.0.1"
-    methods "~1.1.2"
-    on-finished "2.4.1"
-    parseurl "~1.3.3"
-    path-to-regexp "0.1.7"
-    proxy-addr "~2.0.7"
-    qs "6.10.3"
-    range-parser "~1.2.1"
-    safe-buffer "5.2.1"
-    send "0.18.0"
-    serve-static "1.15.0"
-    setprototypeof "1.2.0"
-    statuses "2.0.1"
-    type-is "~1.6.18"
-    utils-merge "1.0.1"
-    vary "~1.1.2"
-
 fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
   version "3.1.3"
   resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
@@ -1203,6 +1211,17 @@ fast-json-stable-stringify@^2.0.0:
   resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
   integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
 
+fast-json-stringify@^5.0.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/fast-json-stringify/-/fast-json-stringify-5.1.0.tgz#dc184049d7eed4f61e34f65e97c0763fd043977f"
+  integrity sha512-IybGfbUc1DQgyrp9Myhwlr1Z5vjV37mBkdgcbuvsvUxv5fayG+cHlTQQpXH9nMwUPgp+5Y3RT7QDgx5zJ9NS3A==
+  dependencies:
+    "@fastify/deepmerge" "^1.0.0"
+    ajv "^8.10.0"
+    ajv-formats "^2.1.1"
+    fast-uri "^2.1.0"
+    rfdc "^1.2.0"
+
 fast-levenshtein@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
@@ -1213,11 +1232,21 @@ fast-redact@^3.0.0:
   resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.1.tgz#790fcff8f808c2e12fabbfb2be5cb2deda448fa0"
   integrity sha512-odVmjC8x8jNeMZ3C+rPMESzXVSEU8tSWSHv9HFxP2mm89G/1WwqhrerJDQm9Zus8X6aoRgQDThKqptdNA6bt+A==
 
+fast-redact@^3.1.1:
+  version "3.1.2"
+  resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.1.2.tgz#d58e69e9084ce9fa4c1a6fa98a3e1ecf5d7839aa"
+  integrity sha512-+0em+Iya9fKGfEQGcd62Yv6onjBmmhV1uh86XVfOU8VwAe6kaFdQCWI9s0/Nnugx5Vd9tdbZ7e6gE2tR9dzXdw==
+
 fast-safe-stringify@^2.0.7, fast-safe-stringify@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884"
   integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==
 
+fast-uri@^2.0.0, fast-uri@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-2.1.0.tgz#9279432d6b53675c90116b947ed2bbba582d6fb5"
+  integrity sha512-qKRta6N7BWEFVlyonVY/V+BMLgFqktCUV0QjT259ekAIlbVrMaFnFLxJ4s/JPl4tou56S1BzPufI60bLe29fHA==
+
 fast-url-parser@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d"
@@ -1225,7 +1254,45 @@ fast-url-parser@^1.1.3:
   dependencies:
     punycode "^1.3.2"
 
-fastq@^1.6.0:
+fastify-metrics@^9.2.2:
+  version "9.2.2"
+  resolved "https://registry.yarnpkg.com/fastify-metrics/-/fastify-metrics-9.2.2.tgz#11a4d6a288db0d365659c809efc3508fa6a36d33"
+  integrity sha512-67PsMy33zCvZk9juIY79YXO/dSLnVhYAV4510uiHfoa/z1VwTIoSkbsEa17JB+VL+KNW3seaSCDacjxOO/OINg==
+  dependencies:
+    fastify-plugin "^4.2.0"
+    prom-client "^14.0.1"
+
+fastify-plugin@^3.0.0, fastify-plugin@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-3.0.1.tgz#79e84c29f401020f38b524f59f2402103fd21ed2"
+  integrity sha512-qKcDXmuZadJqdTm6vlCqioEbyewF60b/0LOFCcYN1B6BIZGlYJumWWOYs70SFYLDAH4YqdE1cxH/RKMG7rFxgA==
+
+fastify-plugin@^4.0.0, fastify-plugin@^4.2.0, fastify-plugin@^4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/fastify-plugin/-/fastify-plugin-4.2.1.tgz#4b80020957938dbc44b8ad4a898fd8bcfbab3f65"
+  integrity sha512-dlGKiwLzRBKkEf5J5ho0uAD/Jdv8GQVUbriB3tAX3ehRUXE4gTV3lRd5inEg9li1aLzb0EGj8y2K4/8g1TN06g==
+
+fastify@^4.5.3:
+  version "4.5.3"
+  resolved "https://registry.yarnpkg.com/fastify/-/fastify-4.5.3.tgz#df4f00347f06e8f3d6ab35788d2d140668c2533c"
+  integrity sha512-Q8Zvkmg7GnioMCDX1jT2Q7iRqjywlnDZ1735D2Ipf7ashCM/3/bqPKv2Jo1ZF2iDExct2eP1C/tdhcj0GG/OuQ==
+  dependencies:
+    "@fastify/ajv-compiler" "^3.1.1"
+    "@fastify/error" "^3.0.0"
+    "@fastify/fast-json-stringify-compiler" "^4.0.0"
+    abstract-logging "^2.0.1"
+    avvio "^8.1.3"
+    find-my-way "^7.0.0"
+    light-my-request "^5.5.1"
+    pino "^8.0.0"
+    process-warning "^2.0.0"
+    proxy-addr "^2.0.7"
+    rfdc "^1.3.0"
+    secure-json-parse "^2.4.0"
+    semver "^7.3.7"
+    tiny-lru "^8.0.2"
+
+fastq@^1.6.0, fastq@^1.6.1:
   version "1.13.0"
   resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
   integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
@@ -1260,18 +1327,13 @@ fill-range@^7.0.1:
   dependencies:
     to-regex-range "^5.0.1"
 
-finalhandler@1.2.0:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
-  integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
+find-my-way@^7.0.0:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/find-my-way/-/find-my-way-7.0.1.tgz#079d6a8b474754e073c75778da678f59dedd620f"
+  integrity sha512-w05SaOPg54KqBof/RDA+75n1R48V7ZZNPL3nR17jJJs5dgZpR3ivfrMWOyx7BVFQgCLhYRG05hfgFCohYvSUXA==
   dependencies:
-    debug "2.6.9"
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    on-finished "2.4.1"
-    parseurl "~1.3.3"
-    statuses "2.0.1"
-    unpipe "~1.0.0"
+    fast-deep-equal "^3.1.3"
+    safe-regex2 "^2.0.0"
 
 find-up@5.0.0, find-up@^5.0.0:
   version "5.0.0"
@@ -1438,6 +1500,17 @@ glob@^7.1.3:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
+glob@^8.0.1:
+  version "8.0.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
+  integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^5.0.1"
+    once "^1.3.0"
+
 globals@^13.15.0:
   version "13.17.0"
   resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4"
@@ -1527,7 +1600,7 @@ he@1.2.0:
   resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
 
-helmet@^5.1.1:
+helmet@^5.0.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/helmet/-/helmet-5.1.1.tgz#609823c5c2e78aea62dd9afc8f544ca409da5e85"
   integrity sha512-/yX0oVZBggA9cLJh8aw3PPCfedBnbd7J2aowjzsaWwZh7/UFY0nccn/aHAggIgWUFfnykX8GKd3a1pSbrmlcVQ==
@@ -1571,13 +1644,6 @@ hyperid@^3.0.0:
     uuid "^8.3.2"
     uuid-parse "^1.1.0"
 
-iconv-lite@0.4.24:
-  version "0.4.24"
-  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
-  integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
-  dependencies:
-    safer-buffer ">= 2.1.2 < 3"
-
 ignore-by-default@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
@@ -1838,11 +1904,25 @@ js-yaml@4.1.0, js-yaml@^4.0.0, js-yaml@^4.1.0:
   dependencies:
     argparse "^2.0.1"
 
+json-schema-resolver@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/json-schema-resolver/-/json-schema-resolver-1.3.0.tgz#0840864b06780363d31fb03cdfae5047e2f81fbb"
+  integrity sha512-EX7W1r8aZ/T3j8GbbBxPXi60bnsELfT90OiA1QrbGMvwzVSbyMNOAzvMFcFb8m7gKCXZLJpGe+cJOvWgoFl29A==
+  dependencies:
+    debug "^4.1.1"
+    rfdc "^1.1.4"
+    uri-js "^4.2.2"
+
 json-schema-traverse@^0.4.1:
   version "0.4.1"
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
   integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
 
+json-schema-traverse@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+  integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
 json-stable-stringify-without-jsonify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
@@ -1873,6 +1953,15 @@ levn@^0.4.1:
     prelude-ls "^1.2.1"
     type-check "~0.4.0"
 
+light-my-request@^5.5.1:
+  version "5.5.1"
+  resolved "https://registry.yarnpkg.com/light-my-request/-/light-my-request-5.5.1.tgz#566d90928b9b960d44b6b2b74e072eec1f7015e4"
+  integrity sha512-Zd4oZjF7axSyc5rYQsbB0qsgY4LFFviZSbEywxf7Vi5UE3y3c7tYF/GeheQjBNYY+pQ55BF8UGGJTjneoxOS1w==
+  dependencies:
+    cookie "^0.5.0"
+    process-warning "^2.0.0"
+    set-cookie-parser "^2.4.1"
+
 lilconfig@2.0.5:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
@@ -2000,16 +2089,6 @@ manage-path@^2.0.0:
   resolved "https://registry.yarnpkg.com/manage-path/-/manage-path-2.0.0.tgz#f4cf8457b926eeee2a83b173501414bc76eb9597"
   integrity sha512-NJhyB+PJYTpxhxZJ3lecIGgh4kwIY2RAh44XvAz9UlqthlQwtPBf62uBVR8XaD8CRuSjQ6TnZH2lNJkbLPZM2A==
 
-media-typer@0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
-  integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
-
-merge-descriptors@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
-  integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
-
 merge-stream@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@@ -2020,7 +2099,7 @@ merge2@^1.3.0, merge2@^1.4.1:
   resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
   integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
 
-methods@^1.1.2, methods@~1.1.2:
+methods@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
   integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
@@ -2038,7 +2117,7 @@ mime-db@1.52.0:
   resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
   integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
 
-mime-types@^2.1.12, mime-types@~2.1.24, mime-types@~2.1.34:
+mime-types@^2.1.12:
   version "2.1.35"
   resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
   integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
@@ -2079,6 +2158,13 @@ minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
   dependencies:
     brace-expansion "^1.1.7"
 
+minimatch@^5.0.1:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
+  integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
+  dependencies:
+    brace-expansion "^2.0.1"
+
 minimist@^1.1.0, minimist@^1.2.0, minimist@^1.2.6:
   version "1.2.6"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
@@ -2163,11 +2249,6 @@ natural-compare@^1.4.0:
   resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
   integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
 
-negotiator@0.6.3:
-  version "0.6.3"
-  resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
-  integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
-
 nise@^5.1.1:
   version "5.1.1"
   resolved "https://registry.yarnpkg.com/nise/-/nise-5.1.1.tgz#ac4237e0d785ecfcb83e20f389185975da5c31f3"
@@ -2253,7 +2334,12 @@ on-exit-leak-free@^0.2.0:
   resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209"
   integrity sha512-dqaz3u44QbRXQooZLTUKU41ZrzYrcvLISVgbrzbyCMxpmSLJvZ3ZamIJIZ29P6OhZIkNIQKosdeM6t1LYbA9hg==
 
-on-finished@2.4.1, on-finished@^2.3.0:
+on-exit-leak-free@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz#5c703c968f7e7f851885f6459bf8a8a57edc9cc4"
+  integrity sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==
+
+on-finished@2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
   integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
@@ -2286,6 +2372,11 @@ onetime@^6.0.0:
   dependencies:
     mimic-fn "^4.0.0"
 
+openapi-types@^11.0.0:
+  version "11.1.0"
+  resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-11.1.0.tgz#037969f3dfa5999423ee33bf889fb0d12984277e"
+  integrity sha512-ZW+Jf12flFF6DXSij8DGL3svDA4RtSyHXjC/xB/JAh18gg3uVfVIFLvCfScUMowrpvlkxsMMbErakbth2g3/iQ==
+
 optionator@^0.9.1:
   version "0.9.1"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
@@ -2308,7 +2399,7 @@ p-finally@^1.0.0:
   resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
   integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
 
-p-limit@^3.0.2:
+p-limit@^3.0.2, p-limit@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
   integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
@@ -2353,11 +2444,6 @@ parent-module@^1.0.0:
   dependencies:
     callsites "^3.0.0"
 
-parseurl@~1.3.3:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
-  integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
-
 path-exists@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
@@ -2383,11 +2469,6 @@ path-parse@^1.0.7:
   resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
   integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
 
-path-to-regexp@0.1.7:
-  version "0.1.7"
-  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
-  integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
-
 path-to-regexp@^1.7.0:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
@@ -2423,6 +2504,14 @@ pino-abstract-transport@^0.5.0, pino-abstract-transport@v0.5.0:
     duplexify "^4.1.2"
     split2 "^4.0.0"
 
+pino-abstract-transport@v1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz#cc0d6955fffcadb91b7b49ef220a6cc111d48bb3"
+  integrity sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==
+  dependencies:
+    readable-stream "^4.0.0"
+    split2 "^4.0.0"
+
 pino-http@^6.5.0:
   version "6.6.0"
   resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-6.6.0.tgz#d0a1deacada8c93327fdaa48f5bdc94bc43d3407"
@@ -2462,6 +2551,11 @@ pino-std-serializers@^5.0.0:
   resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-5.6.0.tgz#31b141155d6520967c5ec72944d08fb45c490fd3"
   integrity sha512-VdUXCw8gO+xhir7sFuoYSjTnzB+TMDGxhAC/ph3YS3sdHnXNdsK0wMtADNUltfeGkn2KDxEM21fnjF3RwXyC8A==
 
+pino-std-serializers@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-6.0.0.tgz#4c20928a1bafca122fdc2a7a4a171ca1c5f9c526"
+  integrity sha512-mMMOwSKrmyl+Y12Ri2xhH1lbzQxwwpuru9VjyJpgFIH4asSj88F2csdMwN6+M5g1Ll4rmsYghHLQJw81tgZ7LQ==
+
 pino@^7.5.0, pino@^7.6.2:
   version "7.11.0"
   resolved "https://registry.yarnpkg.com/pino/-/pino-7.11.0.tgz#0f0ea5c4683dc91388081d44bff10c83125066f6"
@@ -2479,6 +2573,23 @@ pino@^7.5.0, pino@^7.6.2:
     sonic-boom "^2.2.1"
     thread-stream "^0.15.1"
 
+pino@^8.0.0:
+  version "8.4.2"
+  resolved "https://registry.yarnpkg.com/pino/-/pino-8.4.2.tgz#5de76e81b36e173d74244e0af4543e7ae241dbfd"
+  integrity sha512-PlXDeGhJZfAuVay+wtlS02s5j8uisQveZExYdAm9MwwxUQSz9R7Q78XtjM2tTa4sa5KJmygimZjZxXXuHgV6ew==
+  dependencies:
+    atomic-sleep "^1.0.0"
+    fast-redact "^3.1.1"
+    on-exit-leak-free "^2.1.0"
+    pino-abstract-transport v1.0.0
+    pino-std-serializers "^6.0.0"
+    process-warning "^2.0.0"
+    quick-format-unescaped "^4.0.3"
+    real-require "^0.2.0"
+    safe-stable-stringify "^2.3.1"
+    sonic-boom "^3.1.0"
+    thread-stream "^2.0.0"
+
 prelude-ls@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -2494,6 +2605,11 @@ process-warning@^1.0.0:
   resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
   integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==
 
+process-warning@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-2.0.0.tgz#341dbeaac985b90a04ebcd844d50097c7737b2ee"
+  integrity sha512-+MmoAXoUX+VTHAlwns0h+kFUWFs/3FZy+ZuchkgjyOu3oioLAo2LB5aCfKPh2+P9O18i3m43tUEv3YqttSy0Ww==
+
 progress@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
@@ -2506,7 +2622,7 @@ prom-client@^14.0.1:
   dependencies:
     tdigest "^0.1.1"
 
-proxy-addr@~2.0.7:
+proxy-addr@^2.0.7:
   version "2.0.7"
   resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
   integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
@@ -2537,13 +2653,6 @@ punycode@^2.1.0:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
-qs@6.10.3:
-  version "6.10.3"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
-  integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
-  dependencies:
-    side-channel "^1.0.4"
-
 qs@6.9.3:
   version "6.9.3"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e"
@@ -2591,16 +2700,6 @@ range-parser@~1.2.1:
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
   integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
 
-raw-body@2.5.1:
-  version "2.5.1"
-  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
-  integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
-  dependencies:
-    bytes "3.1.2"
-    http-errors "2.0.0"
-    iconv-lite "0.4.24"
-    unpipe "1.0.0"
-
 readable-stream@^3.1.1, readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@@ -2610,6 +2709,13 @@ readable-stream@^3.1.1, readable-stream@^3.6.0:
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
+readable-stream@^4.0.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.1.0.tgz#280d0a29f559d3fb684a277254e02b6f61ae0631"
+  integrity sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==
+  dependencies:
+    abort-controller "^3.0.0"
+
 readdirp@~3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
@@ -2627,6 +2733,11 @@ real-require@^0.1.0:
   resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.1.0.tgz#736ac214caa20632847b7ca8c1056a0767df9381"
   integrity sha512-r/H9MzAWtrv8aSVjPCMFpDMl5q66GqtmmRkRjpHTsp4zBAa+snZyiQNlMONiUmEJcsnaw0wCauJ2GWODr/aFkg==
 
+real-require@^0.2.0:
+  version "0.2.0"
+  resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78"
+  integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==
+
 redis-commands@1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
@@ -2668,6 +2779,11 @@ require-directory@^2.1.1:
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
   integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
 
+require-from-string@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+  integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
 resolve-from@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
@@ -2690,6 +2806,11 @@ restore-cursor@^3.1.0:
     onetime "^5.1.0"
     signal-exit "^3.0.2"
 
+ret@~0.2.0:
+  version "0.2.2"
+  resolved "https://registry.yarnpkg.com/ret/-/ret-0.2.2.tgz#b6861782a1f4762dce43402a71eb7a283f44573c"
+  integrity sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==
+
 retimer@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/retimer/-/retimer-3.0.0.tgz#98b751b1feaf1af13eb0228f8ea68b8f9da530df"
@@ -2700,7 +2821,7 @@ reusify@^1.0.4:
   resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
   integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
 
-rfdc@^1.3.0:
+rfdc@^1.1.4, rfdc@^1.2.0, rfdc@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
   integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
@@ -2731,16 +2852,18 @@ safe-buffer@5.2.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
 
-safe-stable-stringify@^2.1.0:
+safe-regex2@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/safe-regex2/-/safe-regex2-2.0.0.tgz#b287524c397c7a2994470367e0185e1916b1f5b9"
+  integrity sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==
+  dependencies:
+    ret "~0.2.0"
+
+safe-stable-stringify@^2.1.0, safe-stable-stringify@^2.3.1:
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.3.1.tgz#ab67cbe1fe7d40603ca641c5e765cb942d04fc73"
   integrity sha512-kYBSfT+troD9cDA85VDnHZ1rpHC50O0g1e6WlGHVCz/g+JS+9WKLj+XwFYyR8UbrZN8ll9HUpDAAddY58MGisg==
 
-"safer-buffer@>= 2.1.2 < 3":
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
-  integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
-
 secure-json-parse@^2.4.0:
   version "2.5.0"
   resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.5.0.tgz#f929829df2adc7ccfb53703569894d051493a6ac"
@@ -2763,7 +2886,7 @@ semver@~7.0.0:
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
 
-send@0.18.0:
+send@^0.18.0:
   version "0.18.0"
   resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
   integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
@@ -2789,15 +2912,10 @@ serialize-javascript@6.0.0:
   dependencies:
     randombytes "^2.1.0"
 
-serve-static@1.15.0:
-  version "1.15.0"
-  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
-  integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
-  dependencies:
-    encodeurl "~1.0.2"
-    escape-html "~1.0.3"
-    parseurl "~1.3.3"
-    send "0.18.0"
+set-cookie-parser@^2.4.1:
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz#ddd3e9a566b0e8e0862aca974a6ac0e01349430b"
+  integrity sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==
 
 setprototypeof@1.2.0:
   version "1.2.0"
@@ -2887,6 +3005,13 @@ sonic-boom@^2.2.0, sonic-boom@^2.2.1:
   dependencies:
     atomic-sleep "^1.0.0"
 
+sonic-boom@^3.1.0:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-3.2.0.tgz#ce9f2de7557e68be2e52c8df6d9b052e7d348143"
+  integrity sha512-SbbZ+Kqj/XIunvIAgUZRlqd6CGQYq71tRRbXR92Za8J/R3Yh4Av+TWENiSiEgnlwckYLyP0YZQWVfyNC0dzLaA==
+  dependencies:
+    atomic-sleep "^1.0.0"
+
 split2@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809"
@@ -3055,18 +3180,6 @@ supports-preserve-symlinks-flag@^1.0.0:
   resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
   integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
 
-swagger-ui-dist@>=4.11.0:
-  version "4.13.2"
-  resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-4.13.2.tgz#fb814efd51bf06aa8630c0a0af6e3caa48ac6552"
-  integrity sha512-jHL6UyIYpvEI7NsuWd0R3hJaPQTg6Oo4qSBo+oVfOEkv6rrQm/475RGSMmZgV6ajp+Sgrp9CqrDjQYAgQqiv1A==
-
-swagger-ui-express@^4.5.0:
-  version "4.5.0"
-  resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.5.0.tgz#feb1314627092eb9c7e6b65ee018927011445530"
-  integrity sha512-DHk3zFvsxrkcnurGvQlAcLuTDacAVN1JHKDgcba/gr2NFRE4HGwP1YeHIXMiGznkWR4AeS7X5vEblNn4QljuNA==
-  dependencies:
-    swagger-ui-dist ">=4.11.0"
-
 tdigest@^0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/tdigest/-/tdigest-0.1.2.tgz#96c64bac4ff10746b910b0e23b515794e12faced"
@@ -3101,6 +3214,13 @@ thread-stream@^0.15.1:
   dependencies:
     real-require "^0.1.0"
 
+thread-stream@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-2.1.0.tgz#d560dd8b9d09482b0e2e876a96c229c374870836"
+  integrity sha512-5+Pf2Ya31CsZyIPYYkhINzdTZ3guL+jHq7D8lkBybgGcSQIKDbid3NJku3SpCKeE/gACWAccDA/rH2B6doC5aA==
+  dependencies:
+    real-require "^0.2.0"
+
 through@^2.3.8:
   version "2.3.8"
   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
@@ -3111,6 +3231,11 @@ timestring@^6.0.0:
   resolved "https://registry.yarnpkg.com/timestring/-/timestring-6.0.0.tgz#b0c7c331981ecf2066ce88bcfb8ee3ae32e7a0f6"
   integrity sha512-wMctrWD2HZZLuIlchlkE2dfXJh7J2KDI9Dwl+2abPYg0mswQHfOAyQW3jJg1pY5VfttSINZuKcXoB3FGypVklA==
 
+tiny-lru@^8.0.2:
+  version "8.0.2"
+  resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-8.0.2.tgz#812fccbe6e622ded552e3ff8a4c3b5ff34a85e4c"
+  integrity sha512-ApGvZ6vVvTNdsmt676grvCkUCGwzG9IqXma5Z07xJgiC5L7akUMof5U8G2JTI9Rz/ovtVhJBlY6mNhEvtjzOIg==
+
 tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
@@ -3174,14 +3299,6 @@ type-fest@^0.21.3:
   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
   integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
 
-type-is@~1.6.18:
-  version "1.6.18"
-  resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
-  integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
-  dependencies:
-    media-typer "0.3.0"
-    mime-types "~2.1.24"
-
 unbox-primitive@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
@@ -3197,11 +3314,6 @@ undefsafe@^2.0.5:
   resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
   integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
 
-unpipe@1.0.0, unpipe@~1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
-  integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
-
 uri-js@^4.2.2:
   version "4.4.1"
   resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
@@ -3209,21 +3321,11 @@ uri-js@^4.2.2:
   dependencies:
     punycode "^2.1.0"
 
-url-value-parser@^2.0.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/url-value-parser/-/url-value-parser-2.1.0.tgz#fe1ae776122b2eea4bbf284896bbdcd7fc75e1fa"
-  integrity sha512-gIYPWXujdUdwd/9TGCHTf5Vvgw6lOxjE5Q/k+7WNByYyS0vW5WX0k+xuVlhvPq6gRNhzXVv/ezC+OfeAet5Kcw==
-
 util-deprecate@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
   integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
 
-utils-merge@1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
-  integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
-
 uuid-parse@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/uuid-parse/-/uuid-parse-1.1.0.tgz#7061c5a1384ae0e1f943c538094597e1b5f3a65b"
@@ -3239,11 +3341,6 @@ v8-compile-cache@^2.0.3:
   resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
   integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
 
-vary@~1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
-  integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
-
 which-boxed-primitive@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"