How to Set Up Redis as a Managed Service
Provision a production-ready Redis instance in under two minutes: one CLI command creates the container, generates a password, and injects REDIS_URL into linked projects.
Temps Team
June 6, 2026 · 2mo ago
You can run a production-ready Redis instance in under two minutes by provisioning it through Temps: one CLI command creates the container, generates a secure password, binds it to an internal network, and injects REDIS_URL directly into every linked project's environment.
No editing Docker Compose files, no copying connection strings by hand, no configuration drift between environments. Temps manages the lifecycle — create, link, back up, restore, upgrade, and delete — through the dashboard, the CLI, or a coding agent.
TL;DR:
bunx @temps-sdk/cli services create -t redis -n my-cache -yprovisions a managed Redis container. Link it withbunx @temps-sdk/cli services link --id <id> -p <project>andREDIS_URL,REDIS_HOST,REDIS_PORT,REDIS_PASSWORD, andREDIS_DATABASEare injected on the next deploy. Temps is Apache 2.0 — self-host for free on your own server, or use the upcoming Temps Cloud managed add-on (telemetry retention, offsite backups, AI credits) once it ships.
Why run Redis as a managed service instead of configuring it yourself?
Self-managed Redis requires you to handle image upgrades, credential rotation, volume persistence, network isolation, health monitoring, and backup scheduling. Miss any one of those and you risk data loss, stale credentials, or an exposed port.
Temps treats Redis like a first-class infrastructure primitive:
- Auto-generated password (minimum 8 characters, Alphanumeric, 16 characters long) via
requirepasson container start - Internal network isolation — the container joins the Temps private Docker network; its port is never exposed publicly
- Per-project logical database assignment — each linked project gets its own Redis database number (0–15), calculated deterministically from a hash of the project and environment name
- WAL-G RDB snapshot backups to any S3-compatible bucket, when using the default
gotempsh/redis-walg:8-bookwormimage - Live resource limit updates — cap memory, swap, and CPU through the API without restarting the container
- Credential rotation — regenerate the password from the dashboard; linked projects update automatically on the next deploy
How do I provision Redis through Temps?
Step 1: Create the service
# Log in once (stores credentials in ~/.temps)
bunx @temps-sdk/cli login https://your-temps-server.com
# Create a managed Redis instance
bunx @temps-sdk/cli services create -t redis -n my-cache -y
The -y flag accepts all defaults: auto-assigned host port starting from 6379, gotempsh/redis-walg:8-bookworm image, and an auto-generated password.
Via the dashboard:
- Navigate to Services → Create Service.
- Select Redis.
- Choose the image:
- Redis 8 (Managed + WAL-G) (
gotempsh/redis-walg:8-bookworm) — recommended; enables S3 snapshot backups. - Custom image (e.g.
redis:7.2-alpine) — supports local snapshots only.
- Redis 8 (Managed + WAL-G) (
- Click Create Service.
Step 2: Inspect the service
# List services and note the numeric ID
bunx @temps-sdk/cli services list
# Full details including the connection string
bunx @temps-sdk/cli services show --id <id>
Step 3: Link the service to a project
# Inject REDIS_URL and friends into the project's environment
bunx @temps-sdk/cli services link --id <id> -p my-app
# Confirm the injected variables
bunx @temps-sdk/cli services env --id <id> -p my-app
After linking, the next deploy injects five environment variables:
| Variable | Value |
|---|---|
REDIS_URL | redis://:<password>@<container>:6379/<db> |
REDIS_HOST | Container name (used for internal network routing) |
REDIS_PORT | 6379 (internal port) |
REDIS_PASSWORD | Auto-generated password |
REDIS_DATABASE | Deterministic 0–15 number per project+environment |
Step 4: Connect from your application
// Node.js with ioredis — REDIS_URL is injected automatically
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
// Session storage with TTL
await redis.set(`session:${userId}`, JSON.stringify(sessionData), 'EX', 86400);
const session = await redis.get(`session:${userId}`);
# Python with redis-py
import os, redis
r = redis.from_url(os.environ['REDIS_URL'])
r.setex(f'session:{user_id}', 86400, json.dumps(session_data))
// Go with go-redis
import (
"context"
"os"
"github.com/redis/go-redis/v9"
)
opt, _ := redis.ParseURL(os.Getenv("REDIS_URL"))
rdb := redis.NewClient(opt)
rdb.Set(context.Background(), "key", "value", 0)
What environment variables does Temps inject for Redis?
When you link a Redis service to a project, Temps injects connection details as environment variables — verified in temps/crates/temps-providers/src/externalsvc/redis.rs:
REDIS_URL redis://:<password>@<container-name>:6379/<database-number>
REDIS_HOST <container-name> (not localhost — internal Docker network)
REDIS_PORT 6379 (always the internal port)
REDIS_PASSWORD <auto-generated>
REDIS_DATABASE 0–15 (deterministic per project+environment)
The REDIS_DATABASE number is calculated from a hash of the project ID and environment name, so each project/environment combination always gets the same logical database without requiring a Redis connection at configuration time.
Common Redis use cases in production apps
Rate limiting
const key = `rate:${ipAddress}`;
const count = await redis.incr(key);
if (count === 1) await redis.expire(key, 60); // 60-second window
if (count > 100) return res.status(429).json({ error: 'Rate limit exceeded' });
Cache-aside pattern
async function getUser(userId) {
const cached = await redis.get(`user:${userId}`);
if (cached) return JSON.parse(cached);
const user = await db.users.findById(userId);
await redis.set(`user:${userId}`, JSON.stringify(user), 'EX', 300);
return user;
}
Pub/sub for real-time events
// Publisher
await redis.publish('deployments', JSON.stringify({ deployId, status: 'started' }));
// Subscriber (separate connection required for subscribe mode)
const subscriber = new Redis(process.env.REDIS_URL);
subscriber.subscribe('deployments', (message) => {
const event = JSON.parse(message);
console.log(`Deploy ${event.deployId} is ${event.status}`);
});
Queue (list-based FIFO)
// Enqueue
await redis.rpush('jobs', JSON.stringify({ type: 'email', to: user.email }));
// Dequeue (blocking pop — waits up to 30s)
const [, job] = await redis.blpop('jobs', 30);
if (job) await processJob(JSON.parse(job));
How does Redis backup work in Temps?
The default gotempsh/redis-walg:8-bookworm image includes WAL-G, which Temps uses to push RDB snapshot backups to any S3-compatible storage:
- Backup method: WAL-G
backup-push— streams aredis-cli --rdbdump via WAL-G'sWALG_STREAM_CREATE_COMMANDinterface; no data passes through the Temps process - Compression: LZ4 (WAL-G default)
- Restore: Snapshot-based (latest) — no point-in-time recovery for Redis
- Fallback: Custom images without WAL-G fall back to BGSAVE + tar upload
# Check what restore modes are supported
bunx @temps-sdk/cli services restore-capabilities --id <id>
# List available backups
bunx @temps-sdk/cli services list-backups --s3-source-id <s3-source-id>
# Restore from a specific backup
bunx @temps-sdk/cli services restore --id <id> --backup-id <backup-id> -y
For workloads that need point-in-time recovery, use Managed PostgreSQL instead.
How do I upgrade Redis to a newer version?
Temps upgrades the container image while preserving the data volume:
# Upgrade to a specific image
bunx @temps-sdk/cli services upgrade --id <id> -v 8-bookworm
What happens under the hood (verified in redis.rs):
- Temps verifies the new image is pullable from the registry before stopping the old container.
- The old container is stopped.
- A new container is created with the new image, reusing the same named volume (
redis_data_<name>). - The container starts and Temps waits for the Docker healthcheck (
redis-cli ping) to return healthy before returning.
If the new image fails to pull, Temps aborts before touching the running container — the existing instance keeps serving traffic.
How do I set resource limits on a Redis container?
# Via the API (PATCH /api/external-services/{id}/resources)
# Via the dashboard: Services → select service → Resources card → Edit limits
| Field | Meaning | Empty / off |
|---|---|---|
| Memory | Hard memory cap in MiB | Unlimited |
| Swap | Extra swap above the memory cap in MiB | No extra swap |
| CPU | CPU cap in cores | Unlimited |
Limits are applied live via Docker's update API — no container restart needed. When a memory cap is set and the working set exceeds it, the kernel OOM killer terminates the container; the oom_killed flag in GET /api/external-services/{id}/runtime is often the only signal.
Managed Redis comparison: Temps vs. alternatives
| Temps | Upstash | Railway Redis | ElastiCache | Managed on raw VPS | |
|---|---|---|---|---|---|
| Monthly cost | Free to self-host (server cost only); Cloud add-on unpriced, coming soon | $0.2/100k commands | ~$5+/mo | $15+/mo | ~$5/mo infra + ops time |
| Data stays on your server | Yes | No | No | No | Yes |
| Automatic backups | Yes (WAL-G + S3) | Yes | Yes | Yes | Manual |
| Credential injection | Automatic | Manual .env | Manual .env | IAM / .env | Manual |
| Per-project DB isolation | Automatic (hash-based) | Per database | Per database | Per cluster | Manual |
| No per-request pricing | Yes | No | Yes | No | Yes |
| In-dashboard monitoring | Yes | Yes | Yes | Yes | External tools |
Three quotable verified Temps claims about managed Redis
-
Passwords are auto-generated with
--requirepass: TheRedisServicealways callsredis-server --requirepass <password>on container creation; an empty or short-than-8-character password is silently replaced with a 16-character Alphanumeric auto-generated one. (Source:redis.rsdeserialize_optional_password+generate_password) -
Per-project database isolation uses a deterministic hash:
REDIS_DATABASE(0–15) is computed fromstd::hashover"{project_id}_{environment}"— no Redis connection needed to assign it, and the same project always gets the same number after a redeploy. (Source:redis.rscalculate_database_number) -
WAL-G streams the backup; nothing goes through Temps: The backup uses
WALG_STREAM_CREATE_COMMAND="redis-cli --rdb /tmp/redis_backup.rdb && cat /tmp/redis_backup.rdb"— WAL-G runs inside the container and pushes bytes directly to S3. The Temps process never buffers the dump. (Source:redis.rsrun_walg_backup_push)
Frequently asked questions
Is the Redis port exposed to the internet?
No. The container joins the Temps internal Docker network (temps-app-network) and is reachable only from containers on the same network. No host port binding is needed for app-to-Redis traffic; the host port (starting from 6379) is assigned only for administrative access from the server itself.
Can I use Redis Sentinel or Redis Cluster for high availability?
Not yet through the managed service interface. For HA requirements, use the standalone Redis with WAL-G snapshot backups, or run a Postgres cluster (which does support HA through pg_auto_failover).
What happens to data when I delete the service?
Deletion stops the container, removes it, and then removes the Docker volume (redis_data_<name>). This operation is irreversible — download a backup before deleting.
How do I rotate the Redis password?
From the dashboard: Services → select the service → Rotate Credentials. Temps regenerates the password in the service config, updates the running container's requirepass, and queues environment variable updates for all linked projects. They pick up the new REDIS_PASSWORD and REDIS_URL on their next deploy.
Can I bring my own Redis image?
Yes. Pass --docker-image redis:7.2-alpine (or any registry image) at creation time. Custom images that do not include WAL-G will fall back to legacy BGSAVE + tar backups. The docker_image field is updatable post-creation (use services upgrade).
Getting started
# 1. Install or upgrade the CLI
bunx @temps-sdk/cli --version
# 2. Log in to your Temps server
bunx @temps-sdk/cli login https://your-temps-server.com
# 3. Create the Redis service
bunx @temps-sdk/cli services create -t redis -n my-cache -y
# 4. Note the numeric service ID from the output, then link to your project
bunx @temps-sdk/cli services link --id <id> -p <project-name>
# 5. Confirm injected variables
bunx @temps-sdk/cli services env --id <id> -p <project-name>
# 6. Deploy your project to pick up REDIS_URL
bunx @temps-sdk/cli deploy <project-name> -b main -e production -y
Temps Cloud, a managed add-on for telemetry retention, offsite backups, and AI credits, is coming soon at temps.sh; pricing has not been announced yet. Self-hosting is free; see the self-hosted deployment guide to get started on any Linux VPS in under 15 minutes.
Get weekly updates