---
title: "Deploy Redis 8 with RedisInsight UI and Persistence"
description: "Password-protected Redis 8 with JSON, Search, persistence and a web UI."
category: "Storage"
url: https://railway.com/deploy/redis-8-with-redisinsight-ui-and-persist
---

# Deploy Redis 8 with RedisInsight UI and Persistence

Password-protected Redis 8 with JSON, Search, persistence and a web UI.

**[Deploy Redis 8 with RedisInsight UI and Persistence on Railway](https://railway.com/template/redis-8-with-redisinsight-ui-and-persist)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/redis-8-with-redisinsight-ui-and-persist/manifest.json

- **Creator:** bento
- **Category:** Storage
- **Total deploys:** 1

## Template content

### RedisInsight https://cdn.jsdelivr.net/gh/redis/RedisInsight@3.8.0/resources/logo.svg

- **Image:** redis/redisinsight:3.8.0
- **Health check:** /api/health

### Redis https://devicons.railway.app/i/redis.svg

- **Image:** redis:8.10.3
- **Start command:** `/bin/bash -c 'set -eu; D="${RAILWAY_VOLUME_MOUNT_PATH:-/data}"; D="${D%/}"; C=/etc/redis-railway; F="$C/redis.conf"; log() { echo "redis-railway: $*"; }; num() { case "$1" in ""|*[!0-9]*) echo "$2" ;; *) echo "$1" ;; esac; }; low() { echo "$1" | tr "[:upper:]" "[:lower:]"; }; w() { echo "$*" >> "$F"; }; P="${REDIS_PASSWORD:-}"; R="^[A-Za-z0-9._~-]{16,}$"; if [[ ! "$P" =~ $R ]]; then log "REDIS_PASSWORD needs 16+ characters of A-Z a-z 0-9 . _ ~ -"; exit 1; fi; H=$(( $(num "$(grep -m 1 MemTotal /proc/meminfo | tr -s " " | cut -d " " -f 2)" 1048576) * 1024 )); L=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null || echo max); L=$(num "$L" "$H"); if [ "$L" -gt "$H" ]; then L=$H; fi; MM=$(low "${REDIS_MAXMEMORY:-auto}"); PCT=$(num "${REDIS_MAXMEMORY_PERCENT:-75}" 75); if [ "$PCT" -lt 10 ] || [ "$PCT" -gt 95 ]; then PCT=75; fi; R="^[0-9]+([kmg]b?)?$"; if [ -z "$MM" ] || [ "$MM" = auto ]; then MM=$(( L / 100 * PCT )); MS="${PCT}% of ${L}"; elif [[ "$MM" =~ $R ]]; then MS=REDIS_MAXMEMORY; else log "REDIS_MAXMEMORY must be auto, 0 or a size like 512mb"; exit 1; fi; AOF=$(low "${REDIS_APPENDONLY:-yes}"); case "$AOF" in yes|true|on|1) AOF=yes ;; *) AOF=no ;; esac; SAVE=$(low "${REDIS_SAVE-3600 1 300 100 60 10000}"); case "$SAVE" in off|none|no|false) SAVE="" ;; esac; R="^[0-9 ]*$"; if [[ ! "$SAVE" =~ $R ]]; then log "REDIS_SAVE must be seconds/changes pairs or off"; exit 1; fi; mkdir -p "$D"; rm -rf "$D/lost+found"; cd "$D"; M="$D/.railway-appendonly"; PRE=""; if [ "$AOF" = yes ] && [ -s dump.rdb ] && { [ ! -d appendonlydir ] || [ "$(cat "$M" 2>/dev/null || true)" = no ]; }; then if [ -d appendonlydir ]; then rm -rf appendonlydir.stale-*; mv appendonlydir "appendonlydir.stale-$(date -u +%Y%m%dT%H%M%SZ)"; fi; PRE="preload-file rdb:$D/dump.rdb"; log "AOF was off: loading dump.rdb once to build the AOF"; fi; echo "$AOF" > "$M"; chown -R redis:redis "$D"; umask 077; mkdir -p "$C"; : > "$F"; w "bind * -::*"; w "protected-mode yes"; w "requirepass $P"; w "dir $D"; w "appendonly $AOF"; w "appendfsync $(low "${REDIS_APPENDFSYNC:-everysec}")"; if [ -n "$SAVE" ]; then w "save $SAVE"; fi; if [ -n "$PRE" ]; then w "$PRE"; fi; w "maxmemory $MM"; w "maxmemory-policy $(low "${REDIS_MAXMEMORY_POLICY:-noeviction}")"; w "enable-protected-configs no"; w "enable-debug-command no"; w "enable-module-command no"; if [ -n "${REDIS_EXTRA_CONFIG:-}" ]; then echo "$REDIS_EXTRA_CONFIG" >> "$F"; fi; chown -R redis:redis "$C"; export SKIP_FIX_PERMS=1; log "maxmemory $MM ($MS), appendonly $AOF, save ${SAVE:-off}, dir $D"; if [ -z "$SAVE" ]; then exec docker-entrypoint.sh redis-server "$F" --save ""; fi; exec docker-entrypoint.sh redis-server "$F"'`

### RedisInsight Gateway https://cdn.jsdelivr.net/gh/redis/RedisInsight@3.8.0/resources/logo.svg

- **Source:** baranberkay96/redis-railway
- **Health check:** /healthz
- **Public domain:** Yes

### Redis Backup https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/rclone.svg

- **Source:** baranberkay96/redis-railway

## Buckets

- **Bucket**

## Documentation

# Deploy and Host Redis with Railway

Redis is an in-memory data store used as a cache, session store, queue backend and document and vector database. This community template runs Redis 8.10 from the official image with a generated password, AOF and RDB persistence on a volume, the RedisInsight web UI behind a login, and daily backups to a Railway Bucket.

## About Hosting Redis

Running Redis well takes more than starting the server. It needs a password on every connection, persistence that survives restarts and redeploys, a memory cap below the container limit so the kernel does not kill it, and copies of the data outside the volume. This template keeps Railway's Redis service name and variables, so `${{Redis.REDIS_URL}}` references keep working, and adds those pieces: append-only file plus snapshots, a memory cap sized from the service's limit, RedisInsight preconnected to your database behind a password gateway, and a cron job that writes verified RDB backups with retention and can restore them.

## Common Use Cases

- Cache and session store for web apps, with an eviction policy you choose
- Job queues and background workers (BullMQ, Sidekiq, Celery, RQ) that need durable data
- JSON documents with secondary indexes, full-text and vector search through the Redis Query Engine
- Rate limiting, leaderboards, counters, pub/sub and streams
- Time series and probabilistic structures (Bloom, Cuckoo, Count-min, Top-K, t-digest)

## Dependencies for Redis Hosting

- Redis 8.10.3, official `redis` image with the bundled modules (included)
- RedisInsight 3.8.0, official `redis/redisinsight` image (included)
- A Caddy gateway that adds the login in front of RedisInsight (included, built from this repo)
- A Railway Bucket for backups (included, created by the template)

### Deployment Dependencies

- Redis documentation: https://redis.io/docs/latest/
- Redis Docker image: https://hub.docker.com/_/redis
- RedisInsight: https://github.com/redis/RedisInsight
- Caddy basic_auth: https://caddyserver.com/docs/caddyfile/directives/basic_auth
- Railway Storage Buckets: https://docs.railway.com/storage-buckets
- Railway cron jobs: https://docs.railway.com/cron-jobs

### Implementation Details

| Service | Image | Purpose |
|---|---|---|
| Redis | `redis:8.10.3` | Redis with Query Engine, JSON, time series and probabilistic modules plus vector sets; volume at `/data`; TCP proxy for external clients |
| RedisInsight | `redis/redisinsight:3.8.0` | Web UI, private only, preconnected to Redis; volume at `/data` for its settings |
| RedisInsight Gateway | built from `services/redisinsight-gateway` | Public HTTPS entry with a login (Caddy basic auth) |
| Redis Backup | built from `services/backup` | Daily cron (03:20 UTC): RDB snapshot, `redis-check-rdb`, upload, 14-day retention (at least 3 kept) |
| Bucket | Railway Bucket | Private storage for the backups |

**Connecting.** Other Railway services reference `${{Redis.REDIS_URL}}` (private network). `REDISHOST`, `REDISPORT`, `REDISUSER`, `REDISPASSWORD` and `REDIS_PASSWORD` exist with the same names as Railway's Redis. `REDIS_PUBLIC_URL` goes through the TCP proxy for clients outside Railway. It is password-protected but not encrypted, and the traffic is billed as egress. If you do not need it, remove the proxy under Redis → Settings → Networking.

**First login to RedisInsight**

1. Open the public URL of the RedisInsight Gateway service.
2. Log in with `BASIC_AUTH_USERNAME` (`admin`) and `BASIC_AUTH_PASSWORD` from that service's Variables tab.
3. Accept RedisInsight's terms on the first visit, or set `RI_ACCEPT_TERMS_AND_CONDITIONS=true` on the RedisInsight service (analytics and notifications then stay off).
4. Open the database "Redis on Railway". It is already configured with the private hostname and password.

**Cache or store.** By default Redis behaves as a store: `REDIS_MAXMEMORY=auto` caps memory at 75% of the service's memory limit, and `noeviction` refuses writes at the cap instead of deleting keys, which queues need. For a cache, set `REDIS_MAXMEMORY` to a fixed size such as `256mb` and `REDIS_MAXMEMORY_POLICY=allkeys-lru`. On Railway the limit Redis sees can be your plan's per-service maximum, so a cache without a fixed size can grow, and be billed, far beyond what it needs. For a pure cache, also set `REDIS_APPENDONLY=no` and `REDIS_SAVE=off`.

**Persistence.** The append-only file is written with `fsync` every second, so a crash loses at most about one second of writes. RDB snapshots follow Redis's default schedule, and on redeploy Redis writes a final snapshot (`RAILWAY_DEPLOYMENT_DRAINING_SECONDS=60`). If you switch the AOF on later, the start script loads the existing `dump.rdb` once so the data is kept.

**Commands and security.** Every connection needs the password, and protected mode is on. `DEBUG`, `MODULE LOAD` and `CONFIG SET dir/dbfilename`, which attackers use to write files or load code, are disabled. The `default` user keeps every other command, so client libraries and RedisInsight work unchanged. To give an app fewer rights, add an ACL user in `REDIS_EXTRA_CONFIG` (raw editor, one directive per line), for example `user app on >{long-password} ~* &* +@all -@admin -flushall -flushdb`, and test your client with it.

**Backups.** Each run writes `redis/{timestamp}/dump.rdb.gz` and a `MANIFEST.txt` with checksums to the Bucket. Start one now with `railway cron run --service "Redis Backup"`. Runs are listed in the Bucket's Files tab.

**Restore.** Set `BACKUP_RESTORE_RUN` on Redis Backup to a run folder name, deploy, then trigger a run. The job first backs up the current data. It then loads the chosen backup into a temporary Redis inside the job, makes your Redis a replica of it, and promotes it back once the sync is done. All data is replaced, and writes fail with READONLY during the sync. A run is restored only once; clear the variable afterwards. Any Redis 8.10 with the same modules can also load the downloaded `dump.rdb` directly.

**Scaling.** Give Redis more memory in its settings. `auto` follows the new limit at the next restart, or set `REDIS_MAXMEMORY`. Hobby volumes start at 5 GB. The AOF and snapshots together need about twice the data size on disk.

**Versions.** Images are pinned: `redis:8.10.3` and `redis/redisinsight:3.8.0`. To upgrade Redis, change the image tag and the `FROM redis:...` line in `services/backup/Dockerfile` together. Downgrading to an older Redis cannot read newer data files.

**Licenses.** Redis 8 is available under RSALv2, SSPLv1 or AGPLv3, at your choice. RedisInsight is SSPLv1. This is not legal advice: check the terms if you offer Redis to third parties as a service. This template is not affiliated with Redis Ltd.

**Cost.** Roughly $2.50 per month idle and about $10 per month with around 500 MB of data and daily backups, at Railway's usage prices. Most of the idle cost is RedisInsight; you can remove the RedisInsight and RedisInsight Gateway services and keep Redis, backups and the Bucket.

### Why Deploy Redis on Railway?

Railway runs Redis, its web UI and the backup job together on a private network, with persistent volumes and a managed bucket, so you get a protected Redis with a UI in a few minutes without managing servers. Apps in the same project connect through `${{Redis.REDIS_URL}}`, and you grow it by raising the service limits and the volume size.


## Similar templates

- [RustFS | (Just Updated) S3 Object Store, Public URL and Keys Set](https://railway.com/deploy/rustfs-or-just-updated-s3-object-store-p) — S3-compatible object store, keys and public URL preset, volume kept
- [TimescaleDB](https://railway.com/deploy/timescaledb-railway-template) — A PostgreSQL-based time-series database for analytics on Railway.
- [Garage S3 Storage](https://railway.com/deploy/garage-s3-storage) — Ultra-light S3 server: fast, open-source, plug-and-play.

Open this page in a browser: https://railway.com/deploy/redis-8-with-redisinsight-ui-and-persist
