Skip to content

ElastiCache Valkey

2 min read · main part only; folded sections are optional

After this you can answer: What does the cache hold, and what happens to MiniTickets when it disappears?

flowchart TB
API["api tasks<br/>use api-sg"] -->|"rediss:// TCP 6379"| V[("minitickets-dev-valkey")]
V --- S["sessions"]
V --- C["events cache"]
V --- R["rate limits"]
V --- G["seat gate"]
  1. Shared memory. Every api task talks to the same Valkey node, so a session made by one task works on the next.
  2. Allowed. redis-sg allows TCP 6379 only from api-sg.
  3. Password and TLS. Every connection must use TLS (the s in rediss://) and send the auth token. Both come in the REDIS_URL secret.
  4. Data can expire or be replaced. Sessions expire after 7 days; cached lists and rate buckets sooner. Seat state is advisory and rebuilt from Postgres. Dev accepts this loss without backups.

minitickets-dev-valkey is a replication group with one cache.t4g.micro node, Valkey 8.2, port 6379, in the private subnets, with encryption in transit and at rest (infra/src/data/cache.ts → createCache). One node means no replica and no automatic failover.

Each layer handles its own Redis error differently:

UseWhen Valkey fails
SessionsRequests with a session cookie fail; lost records require log-in
Events cacheUses Postgres; each Redis operation has a 100 ms timeout
Rate limitsFails closed: 503, so log-in floods stay bounded
Seat gateSkipped: Postgres decides alone

These are layer behaviors, not a whole-request fallback. Session lookup runs first. A full outage can fail a request before it reaches the cache or gate (apps/api/src/trpc/context.ts → createContext).

From → toWhat happensWhat allows it
ElastiCache Valkey → Private subnetsonly when dataEnabled = truethe cache lives in the private subnets
  • config cache subnet group minitickets-dev-valkey-subnets (both private subnets)createCache
ElastiCache Valkey → Cache security grouponly when dataEnabled = truethe cache uses the redis security group
API ECS service → ElastiCache Valkeyonly when computeEnabled = truethe Redis protocol over TLS (rediss://) on port 6379
  • sg-rule redis-sg inbound rule minitickets-dev-redis-in-6379: TCP 6379 from api-sgcreateSecurityGroups
  • route local route 10.0.0.0/16: a public subnet reaches a private subnet without leaving the VPCcreateNetwork
  • secret REDIS_URL from minitickets/dev/redis-url, which holds the Valkey auth tokencreateSecrets
Sessions → ElastiCache Valkeyonly when dataEnabled = truesession:<hash> keys with a 7-day TTL
  • code only queries/sessions.ts touches the session keyscreate
Events list cache → ElastiCache Valkeyonly when dataEnabled = truethe cached lists and the generation key
Rate limiter → ElastiCache Valkeyonly when dataEnabled = trueone token bucket per scope and caller
  • code queries/rate-limits.ts runs the TAKE_TOKEN Lua scripttakeToken
Inventory gate → ElastiCache Valkeyonly when dataEnabled = trueseat counters and leases per event
  • code queries/inventory.ts runs the RESERVE and SETTLE Lua scriptsreserve
See Valkey on the map →

ElastiCache → Valkey caches → minitickets-dev-valkey: Primary endpoint, Encryption in transit: Enabled, then the Events tab.

SymptomCauseWhere to look
Existing sessions stop workingSession lookup failed or records were lostAPI log; ElastiCache → Events
Log-in without a session cookie returns 503redis-sg no longer allows api-sgredis-sg → Inbound rules
Connection resets in the API logURL uses redis://, TLS is requiredThe REDIS_URL secret format
How would you make it highly available?

Two or more nodes in two availability zones with automaticFailoverEnabled and multiAzEnabled. A replica takes over when the primary fails. Replicas add cost; dev keeps one node. Asynchronous replication can still lose recent writes during failover. See AWS replication behavior.

Why does the rate limiter fail closed, but the cache fails open?

The cache only saves work: without it Postgres answers, a bit slower. The limiter protects expensive password hashing; without it a flood could run unbounded, so refusing is safer.

Why Valkey and not Redis?

Valkey is an open-source fork of Redis. Our Redis commands and ioredis client work with it. That keeps our local Redis and AWS Valkey code the same; see Valkey’s compatibility guide.

Advanced: Why a replication group with one node

A node-based replication group gives us a primary now and optional replicas later. Our token is a random 32-character string of letters and digits, safe inside the URL. Both encryption settings are on from the start. AWS allows changing in-transit encryption on Valkey 7.2 and later, while at-rest encryption is set only at creation. This corrects the older comment in infra/src/data/cache.ts.

Answer these without scrolling up. If one feels hard, reread that section.

  1. Name the four things MiniTickets keeps in Valkey.
  2. Which rule allows the api to connect, on which port?
  3. What two things protect each connection?
  4. Why are there no backups?
  5. Which use fails closed, and why?

Redraw it from memory: the api tasks, Valkey, and its four uses

Try this: on the map, play the booking flow and open the failure branch of the sessions step

Read this book online: https://book.theversehub.in/