尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗ElastiCache / Redis bills by the hour while idle. dynamoredis does the same job on one DynamoDB table behind a Lambda Function URL and costs ≈ $0 when nothing happens. Same client API (redis-py); when you outgrow it, go back to a real Redis by changing one import line.
中文 · compatibility report · tasks · changelog
| ElastiCache Serverless (Redis) | dynamoredis | |
|---|---|---|
| Idle cost / month | ~$90 — billed per GB-hour with a 1 GB minimum ($0.125 × 24 × 30), ECPUs on top | ≈ $0 |
| Endpoint | host:6379, RESP protocol, VPC | Lambda Function URL, HTTPS, anywhere |
| Storage | memory on nodes | one DynamoDB table (pay per request, TTL, multi-AZ, durable) |
| Client | import redis | from dynamoredis import redis |
| Console | RedisInsight | built-in web console (Lambda URL) |
| Client compatibility | — | see the report |
Most Redis use is a cache, a few counters, sessions, a small queue — bursts of activity and long idle stretches, for which ElastiCache Serverless still charges every hour for at least 1 GB (≈ $90 a month before a single request). DynamoDB already is a serverless key-value store with atomic counters, sets, lists and TTL; what is missing is the Redis API. dynamoredis adds it: a Lambda translates redis commands into DynamoDB calls, the driver speaks redis-py.
Your code calls the Lambda Function URL with HTTP Basic auth (the service's user / password); the Lambda
runs each command against one DynamoDB table — item = key, type, value, optional expiry. Where Redis is
atomic, DynamoDB is atomic: INCR is an ADD, LPUSH is list_append, SADD is a set ADD, a type
mismatch is a condition failure (WRONGTYPE). Expiry is honoured on read at once; DynamoDB's TTL sweep
deletes the item later. Durable the moment a command returns, multi-AZ, no node to run out of memory.
Terraform
cp terraform/example.json terraform/my.json # set aws_profile, env, console_auth_username, console_auth_password
terraform -chdir=terraform init
terraform -chdir=terraform apply -var-file=my.json
terraform -chdir=terraform output # console_url
terraform -chdir=terraform destroy -var-file=my.json # tear everything down (the table included)
CloudFormation (AWS CLI only)
cp cloudformation/example-params.json cloudformation/params.json
aws cloudformation package --template-file cloudformation/template.yaml \
--s3-bucket <any-bucket-you-own> --output-template-file /tmp/dynamoredis.yaml
aws cloudformation deploy --template-file /tmp/dynamoredis.yaml --stack-name dynamoredis \
--capabilities CAPABILITY_IAM --parameter-overrides file://cloudformation/params.json
Both create one DynamoDB table (<name>-<env>, pay per request, TTL on exp), one Lambda with a public
Function URL, and one scoped IAM role.
Open console_url in a browser, sign in with user / password. Keys by prefix on the left (SCAN), the
value on the right by type (string, hash, list, set, sorted set) with its TTL, a command line on top —
SET greeting hello, HGETALL user:1, ZADD board 10 alice. Every call shows the server time and the
DynamoDB capacity units it consumed.
Paste this into the command box to get a small dataset to click around (one command per line; FLUSHDB clears it):
HSET user:tom name Tom age 31 city Boston
HSET user:mary name Mary age 28 city Seattle
HSET user:alice name Alice age 30 city Austin
SET user:tom:last_login 2026-10-26T05:00:00Z
INCR user:tom:visits
SADD user:tom:roles admin editor
ZADD user:leaderboard 120 tom 95 mary 150 alice
RPUSH user:tom:inbox "hello tom" "meeting at 3"
SET config:feature:dark_mode on
SETEX session:abc123 3600 tom
INCR counter:pageviews
LPUSH jobs:pending job-1 job-2
Then look at the DynamoDB table in the AWS console: one item per key — t is the type, v the value
(hash = Map, list = List, set = String Set, sorted set = Map of member → score, counters = Number),
session:abc123 carries exp.
pip install dynamoredis
from dynamoredis import redis # later: `import redis` against a real Redis, nothing else changes
r = redis.Redis(host="xxx.lambda-url.us-east-2.on.aws", username="admin", password="...")
r.set("greeting", "hello", ex=60)
r.get("greeting") # b"hello" (decode_responses=True -> "hello")
r.incr("hits") # atomic
r.hset("user:1", mapping={"name": "alice", "age": 30}); r.hgetall("user:1")
r.rpush("queue", "job-1", "job-2"); r.lpop("queue")
r.zadd("board", {"alice": 10, "bob": 20}); r.zrange("board", 0, -1, withscores=True)
with r.pipeline(transaction=False) as p: # one HTTP request for the batch
p.set("a", 1); p.get("a"); p.execute()
tests/compat/REPORT.md is regenerated by every test run: the same redis-py calls run on a real Redis 7 (Docker) and on dynamoredis, comparing replies (type included) and errors.
| Status | Meaning |
|---|---|
| ✅ verified | identical to redis-py against Redis 7; safe to rely on |
| ❌ gap | known difference; the note names the task in TASKS.md that closes it |
| ⚪ quirk | documented behaviour of Redis we deliberately do not imitate |
| ⛔ unsupported | refused with NotSupportedError — never silently different |
Run it yourself — the same commands CI runs on every push:
以上為 README 的開頭部分。其餘內容請閱讀原文。 檢視完整 README ↗