At a glance
What this guide adds to the Express application:Environment variables
The Express application’s own variables are in its table. The internal connection also adds
REDIS_URL, which redis.js doesn’t read.
Before you begin
- An Express application deployed on Sevalla, as in Deploy Express.
- Node.js 20 or later in the application, which ioredis 6 needs. The Express guide pins Node.js 24.
Create a Redis database
1
Create the database
In the sidebar, click Databases, then click Create database. Under Database, choose Redis or Valkey and the version. Enter
storefront-redis as the Display name, choose the same Data center as the application and a Size, then click Create database. See Create a database for every field.2
Connect it to the application
In the sidebar, click Applications, then click the application. Click the Networking tab. Under Connected services, click Add internal connection. Choose
storefront-redis as the Service, turn on Add environment variables to the application, and click Add internal connection. Only services in the application’s location are listed.
Redis and Valkey databases have a password but no username, and clients use logical database
0. See Connect an application.
Install ioredis
Create the client
Create one client for the whole application, from the separate variables:redis.js
new Redis(process.env.REDIS_URL): REDIS_URL starts with redis:// for Redis and Valkey. A Valkey REDIS_URL added before Oct 30, 2026 starts with valkey://, which ioredis doesn’t parse as a URL.
ioredis reconnects on its own when the connection drops, and queues commands until it’s back.
Cache a slow response
Add a route toserver.js that keeps its result in Redis for 60 seconds:
server.js
EX 60 makes Redis delete the key after 60 seconds, so the next request loads fresh data. Delete the key with redis.del("products") when the data changes. The SIGTERM handler runs on every deployment: Ingot’s image starts the server under tini, which passes the stop signal on to Node.js.
Deploy and verify
Commit and push the changes,package-lock.json included: Ingot installs ioredis from it with npm ci and starts the server from the start script as before. With auto-deploy on, the push starts a deployment; otherwise, start one with Deploy now on the application’s Overview tab. The deployment also gives the application the variables the internal connection added. When the deployment’s status changes to Deployed:
-
Request the route twice. Use your application’s domain instead of
storefront-x7k2m.sevalla.app:The first response has the headerx-cache: missand takes about a second. The second hasx-cache: hitand returns at once. -
On the database’s Redis studio tab, the
productskey appears with its value until it expires. See Database studio.
Use Redis from other processes
Environment variables belong to the application, so its background workers and cron jobs get the sameREDIS_* variables as the web process. Import the same redis.js in a worker to process a queue, or store sessions in Redis with your framework’s Redis session store so that a visitor stays signed in on every instance.
Deploy with the API
This sequence adds the Redis database of this guide to the application from Deploy Express through the Sevalla API, so an agent or a script can run it as is.APP_ID is that application, and the changes on this page are pushed to its branch. Each step names the operation, shows the curl command, and gives the matching CLI command and MCP server tool.
You need an API key with the Company developer role in the SEVALLA_API_KEY environment variable (the CLI reads the same key from SEVALLA_API_TOKEN), and curl, jq and openssl. A call that fails returns status and message instead of the resource, and jq -r .id prints null: stop and read the message.
1
Look up the location and the database size
Get application (CLI:
getApplicationV3) returns the application’s location in cluster_id; the database must be in the same one. List database resource types (listDatabaseResourceTypesV3) returns the database sizes; DB1 is the smallest.sevalla apps get "$APP_ID" and sevalla resources db-types. MCP: get_application and get_platform_options.2
Create the database
Create database (CLI:
createDatabaseV3) starts creating a Redis 8.6 database with a password you generate. List database versions (listDatabaseVersionsV3) lists the versions of a location; a Valkey database works the same way with "type": "valkey".sevalla databases create --name storefront-redis --type redis --db-version 8.6 --cluster "$CLUSTER_ID" --resource-type "$DB_SIZE_ID" --db-name storefront --db-password "$DB_PASSWORD". MCP: create_database, which generates a password and doesn’t return it; set one you know afterwards with sevalla_api_update, resetDatabasePasswordV3 and {"new_password": "..."}.3
Connect the database
Create internal connection (CLI:
createDatabaseInternalConnectionV3) connects the database to the application over the private network. Unlike the dashboard, it adds no environment variables: a later step adds them.sevalla databases connections internal-create "$DB_ID" --target-id "$APP_ID" --target-type app. MCP: sevalla_api_create with createDatabaseInternalConnectionV3.4
Read the database details
Get database (CLI:
getDatabaseV3) returns the database’s internal hostname and port. The loop waits until its status is ready.sevalla databases get "$DB_ID" --json. MCP: get_database.5
Add the environment variables
Create environment variable (CLI:
createEnvironmentVariableV3) adds one variable per call. add_var sends each one as available during runtime only. These are the variables the dashboard’s internal connection adds, except REDIS_URL, which the code doesn’t read:sevalla apps env-vars create "$APP_ID" --key REDIS_HOST --value "$(jq -r .internal_hostname <<< "$DB")", once per variable; the CLI makes each one available during the build too. MCP: set_environment_variables with the three variables in one call, each with runtime true and buildtime false.6
Deploy
Trigger deployment (CLI:
triggerDeploymentV3) builds the latest commit of the branch and rolls it out.sevalla apps deployments trigger "$APP_ID". MCP: trigger_deployment.7
Wait for the deployment
Get deployment (CLI:
getDeploymentV3) returns the deployment’s status: waiting, then inProgress, then success or failed. The loop polls every 15 seconds for up to 30 minutes and keeps polling through a failed request.sevalla apps deployments get "$DEPLOYMENT_ID" --app-id "$APP_ID". MCP: get_deployment.8
Check the deployment
List application domains (The first request misses the cache and the second hits it:CLI:
listApplicationDomainsV3) returns the application’s domain. Request the route twice and read the X-Cache header:sevalla apps domains list --app-id "$APP_ID". MCP: get_application.