diff --git a/index.js b/index.js
index b6179c6a8070e192547ef7aef14188c9c1f0a3fb..e9ca732accb4166e81c4652d178f37814c7a0ec9 100644
--- a/index.js
+++ b/index.js
@@ -2,80 +2,5 @@
 // Note: actual env vars supersede .env file and .env file supersedes .env.defaults file
 require('dotenv-defaults').config()
 
-// Ignore paths for logging, metrics and docs
-const ignorePaths = ['/ready', '/healthy']
-
-// Fast, minimalist web framework for node.
-const express = require('express')
-
-// Helmet helps you secure your Express app by setting various HTTP headers
-const helmet = require('helmet')
-
-// Very low overhead Node.js logger. Logs in json use pino-pretty for dev.
-const logger = require('pino')()
-
-// Fastest HTTP logger for Node.js in town
-const httpLogger = require('pino-http')({ logger, autoLogging: { ignorePaths } })
-
-// Readiness and liveness checks middleware
-const health = require('@cloudnative/health-connect')
-const healthCheck = new health.HealthChecker()
-
-// Prometheus middleware for standard api metrics
-const apiMetrics = require('prometheus-api-metrics')
-
-// Swagger UI for api-docs
-const swaggerUi = require('swagger-ui-express')
-const yaml = require('js-yaml')
-const fs = require('fs')
-const swaggerDocument = yaml.load(fs.readFileSync('./swagger.yaml', 'utf8'))
-
-// The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
-const app = express()
-
-const fetch = require('node-fetch')
-
-// Application-level middleware
-app.use(httpLogger)
-app.use(helmet())
-app.use('/healthy', health.LivenessEndpoint(healthCheck))
-app.use('/ready', health.ReadinessEndpoint(healthCheck))
-app.use(apiMetrics({ excludeRoutes: ignorePaths }))
-app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
-app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
-
-const urls = yaml.load(fs.readFileSync('./config/manifests/urls.yaml', 'utf8')).manifests
-
-let manifestCache = []
-let lastCached
-
-const getManifests = async () => {
-  if (+new Date() < lastCached + 30000) return
-  const results = urls.map(url => fetch(url).then(result => {
-    if (!result.ok) throw new Error(`Failed to load manifest for url ${result.url} (Status: ${result.status}: ${result.statusText})`)
-    return result.json().catch(err => { throw new Error(`Failed to load manifest for url ${result.url}: ${err}`) })
-  }))
-  manifestCache = (await Promise.all(results)).flat()
-  lastCached = +new Date()
-}
-
-getManifests()
-
-app.get('/api/manifest.json', async (req, res, next) => {
-  try {
-    getManifests()
-    res.json(manifestCache || [])
-  } catch (err) {
-    next(err)
-  }
-})
-
-app.use(function (err, req, res, next) {
-  logger.error(err)
-  res.status(500).end()
-})
-
-// Binds and listens for connections on the specified host and port
-app.listen(process.env.PORT, () => {
-  logger.info(`manifest-service listening on port ${process.env.PORT}`)
-})
+const createApp = require('./src/server')
+createApp()
diff --git a/src/server.js b/src/server.js
new file mode 100644
index 0000000000000000000000000000000000000000..a85d9813138b3e2b510c35bb55b8cbb494a83ae6
--- /dev/null
+++ b/src/server.js
@@ -0,0 +1,91 @@
+// Ignore paths for logging, metrics and docs
+const ignorePaths = ['/ready', '/healthy']
+
+// Fast, minimalist web framework for node.
+const express = require('express')
+
+// Helmet helps you secure your Express app by setting various HTTP headers
+const helmet = require('helmet')
+
+// Very low overhead Node.js logger. Logs in json use pino-pretty for dev.
+const logger = require('pino')()
+
+// Fastest HTTP logger for Node.js in town
+const httpLogger = require('pino-http')({ logger, autoLogging: { ignorePaths } })
+
+// Readiness and liveness checks middleware
+const health = require('@cloudnative/health-connect')
+
+// Prometheus middleware for standard api metrics
+const apiMetrics = require('prometheus-api-metrics')
+
+// Swagger UI for api-docs
+const swaggerUi = require('swagger-ui-express')
+const yaml = require('js-yaml')
+const fs = require('fs')
+const fetch = require('node-fetch')
+const swaggerDocument = yaml.load(fs.readFileSync('./swagger.yaml', 'utf8'))
+
+// The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
+
+module.exports = () => {
+  const app = express()
+
+  const healthCheck = new health.HealthChecker()
+
+  // Application-level middleware
+  app.use(httpLogger)
+  app.use(helmet())
+  app.use('/healthy', health.LivenessEndpoint(healthCheck))
+  app.use('/ready', health.ReadinessEndpoint(healthCheck))
+  app.use(apiMetrics({ excludeRoutes: ignorePaths }))
+  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument))
+  app.use('/swagger.json', (req, res) => res.json(swaggerDocument))
+
+  const isReady = async () => {
+    await fetchManifest()
+    if (manifestCache.length === 0) throw new Error('No manifests found.')
+  }
+
+  const readinessCheck = new health.ReadinessCheck('readinessCheck', isReady)
+  healthCheck.registerReadinessCheck(readinessCheck)
+
+  const livenessCheck = new health.LivenessCheck('livenessCheck', isReady)
+  healthCheck.registerLivenessCheck(livenessCheck)
+
+  const urls = yaml.load(fs.readFileSync('./config/manifests/urls.yaml', 'utf8')).manifests
+
+  let manifestCache = []
+  let lastCached
+
+  const fetchManifest = async () => {
+    if (+new Date() < lastCached + 30000) return
+    const results = urls.map(url => fetch(url).then(result => {
+      if (!result.ok) throw new Error(`Failed to load manifest for url ${result.url} (Status: ${result.status}: ${result.statusText})`)
+      return result.json().catch(err => { throw new Error(`Failed to load manifest for url ${result.url}: ${err}`) })
+    }))
+    manifestCache = (await Promise.all(results)).flat()
+    lastCached = +new Date()
+  }
+
+  app.get('/api/manifest.json', async (req, res, next) => {
+    try {
+      await fetchManifest()
+      res.json(manifestCache || [])
+    } catch (err) {
+      next(err)
+    }
+  })
+
+  app.use(function (err, req, res, next) {
+    logger.error(err)
+    res.status(500).end()
+  })
+
+  // Binds and listens for connections on the specified host and port
+  app.listen(process.env.PORT, () => {
+    logger.info(`manifest-service listening on port ${process.env.PORT}`)
+  })
+
+  return app
+}