Redge is a Redis/Valkey protocol compatible edge KV server backed by SQL databases.
This first implementation includes:
- RESP2 TCP listener.
- Public HTTP status server for platform health checks.
- Redis client compatibility for common string, TTL, sorted set, scan, pipeline, and simple transaction flows.
- GUI-friendly inspection commands such as
TYPE,DBSIZE,STRLEN, andMEMORY USAGE. - Multi-database support through
DATABASE_URL: SQLite, libSQL/Turso, PostgreSQL, MySQL, and Cloudflare D1. - L1 in-memory cache powered by Ristretto/TinyLFU with TTL, max keys, max bytes, and admin metrics.
- Admin HTTP server with health, cache metrics, cleanup, paginated key inspection, single-key deletion, and sorted-set inspection.
go mod tidy
go run ./cmd/redgeThen test:
curl.exe http://127.0.0.1:8080/health
curl.exe http://127.0.0.1:8080/ready
redis-cli -p 6379 ping
redis-cli -p 6379 set hello world ex 60
redis-cli -p 6379 get helloRedge exposes two different protocols:
- HTTP status on container port
8080. - Redis/Valkey TCP on container port
6379.
Point your Coolify domain, for example https://test1.conn.redgedb.com, to port 8080. That URL is for /health, /ready, and /version; it is not a Redis URL.
Expose Redis by making container port 6379 public as a TCP/public port in Coolify. Clients connect with the domain plus that public port:
redis://:PASSWORD@test1.conn.redgedb.com:PUBLIC_PORT/0
For public encrypted Redis, enable native Redis TLS and use rediss://:
rediss://:PASSWORD@test1.conn.redgedb.com:PUBLIC_PORT/0
If you map host port 6379 directly to container port 6379, clients can use:
redis://:PASSWORD@test1.conn.redgedb.com:6379/0
Prefer object-style client config when your library supports it:
host=test1.conn.redgedb.com
port=6379
password=PASSWORD
db=0
If PASSWORD contains URL-significant characters like @, :, /, #, ?, or %, URL-encode it before putting it in a redis:// URL.
Recommended production variables:
REDGE_ENV=production
REDGE_PROTECTED_MODE=true
REDGE_REQUIRE_AUTH=true
REDGE_PASSWORD=<strong-random-password>
DATABASE_URL=sqlite:///data/redge.db
REDGE_ADMIN_ENABLED=false
REDGE_MAX_CONNECTIONS=1000Use a persistent volume mounted at /data when using the default SQLite database.
Security presets:
- Private recommended: route HTTPS to
8080, do not publish6379, and access Redis through a private network, VPN, tunnel, or internal service discovery. KeepREDGE_REQUIRE_AUTH=true. - Public strong: publish TCP
6379, enableREDGE_TLS_ENABLED=true, provide cert/key through base64 env secrets or mounted files, use a long randomREDGE_PASSWORD, and setREDGE_ALLOWED_IPSwhen client IPs are known.
Coolify's HTTPS domain protects only the HTTP status route. It does not automatically encrypt Redis TCP, so public Redis clients should use rediss:// with TLS enabled in Redge.
This repo includes nixpacks.toml with Go 1.25 build and a startup command that maps platform PORT to the HTTP status server.
Recommended environment variables:
REDGE_ENV=production
DATABASE_URL=sqlite:///data/redge.db
REDGE_ADMIN_ENABLED=false
REDGE_HTTP_ENABLED=true
# Optional:
# REDGE_ADDR=0.0.0.0:6379
# PORT=8080
# ADMIN_PORT=9090Notes:
- If your platform sets
PORT, Redge will bind HTTP status to0.0.0.0:${PORT}. - Redis TCP remains on
REDGE_ADDR, defaulting to0.0.0.0:6379. - If you want admin HTTP on a second port, set
REDGE_ADMIN_ENABLED=trueandADMIN_PORT.
Build and run:
docker build -t redge:latest .
docker run --rm -p 8080:8080 -p 6379:6379 -e REDGE_REQUIRE_AUTH=true -e REDGE_PASSWORD=<strong-random-password> redge:latestProduction-like example with persistent SQLite data:
docker run -d --name redge \
-p 8080:8080 \
-p 6379:6379 \
-v redge_data:/data \
-v /path/to/certs:/certs:ro \
-e REDGE_ENV=production \
-e REDGE_PROTECTED_MODE=true \
-e REDGE_REQUIRE_AUTH=true \
-e REDGE_PASSWORD=<strong-random-password> \
-e REDGE_TLS_ENABLED=true \
-e REDGE_TLS_CERT_FILE=/certs/fullchain.pem \
-e REDGE_TLS_KEY_FILE=/certs/privkey.pem \
-e DATABASE_URL=sqlite:///data/redge.db \
-e REDGE_ADMIN_ENABLED=false \
redge:latestIf you do not want to mount certificate files, set base64 env values instead:
REDGE_TLS_ENABLED=true
REDGE_TLS_CERT_B64=<base64-fullchain-pem>
REDGE_TLS_KEY_B64=<base64-private-key-pem>Generate those values from certificate files:
[Convert]::ToBase64String([IO.File]::ReadAllBytes("fullchain.pem"))
[Convert]::ToBase64String([IO.File]::ReadAllBytes("privkey.pem"))The Docker image maps platform PORT to the HTTP status server automatically. Redis TCP stays on 6379 unless you set REDGE_ADDR.
DATABASE_URL=sqlite://redge.db
DATABASE_URL=libsql://example.turso.io
TURSO_AUTH_TOKEN=...
DATABASE_URL=postgres://user:pass@localhost:5432/redge?sslmode=disable
DATABASE_URL=mysql://user:pass@tcp(localhost:3306)/redge?parseTime=true
DATABASE_URL=d1://cloudflare_account_id/d1_database_id
D1_API_TOKEN=...
# Quick D1 connection-string form:
DATABASE_URL=d1://cloudflare_account_id/d1_database_id?apiToken=cloudflare_tokenD1 uses github.com/pubflow/d1http directly instead of GORM or database/sql, so Redge can preserve D1 metadata and avoid fake SQL transaction semantics on the hot path.
For production, prefer keeping D1 tokens in D1_API_TOKEN; when a token is embedded in DATABASE_URL, Redge extracts it and sanitizes the resolved URL before use.
Supported connection and server commands:
AUTH,PING,ECHO,QUIT,SELECT,CLIENT SETNAME,CLIENT GETNAME,INFO,COMMAND,DBSIZE.
Supported string and TTL commands:
GET,SET,SETEX,DEL,EXISTS,TYPE,STRLEN,MEMORY USAGE,EXPIRE,TTL,PTTL,INCR,DECR,INCRBY,DECRBY.
Supported sorted set commands:
ZADD,ZCARD,ZREM,ZREMRANGEBYSCORE,ZRANGE,ZSCORE,ZCOUNT.
Supported iteration and batching behavior:
SCANwithMATCHandCOUNT.- RESP pipelining from clients like ioredis.
- Simple
MULTI,EXEC, andDISCARDqueued execution.
Supported admin inspection routes:
GET /admin/v1/keys?match=session:*&cursor=0&count=100GET /admin/v1/keys/{key}DELETE /admin/v1/keys/{key}GET /admin/v1/zsets/{key}?start=0&stop=99
Cloudflare D1 notes:
- D1 schema migrations use
d1http.BatchRawwhere it is safe. - Parameterized hot-path commands use single prepared HTTP calls because the D1 HTTP API rejects multiple statements with params in one
/rawrequest. - ioredis pipeline correctness is supported at the Redis protocol layer. True D1 write coalescing for arbitrary client pipelines needs a dedicated server-side coalescer because Redis pipelining has no explicit begin/end marker on the wire.
Not supported yet:
- Redis Cluster, Lua scripting, Pub/Sub, Streams, hashes, sets, lists, blocking list commands,
KEYS,WATCH/UNWATCH, geospatial commands, and probabilistic data structures.