1. Measure the cluster
| Metric | Watch |
|---|---|
DatabaseMemoryUsagePercentage | Steady < 50% for weeks = oversized; > 80% = risk of evictions |
Evictions | Non-zero with allkeys-* policy means memory pressure (or intended LRU use) |
EngineCPUUtilization | The engine is mostly single-threaded per shard; high = shard hot |
NetworkBytesIn/Out, NetworkBandwidthOutAllowanceExceeded | Node network limits hit before memory |
CurrConnections, NewConnections | Connection churn from clients without pooling |
CacheHitRate (or hits/misses) | Low hit rate = cache not helping, check TTLs and key design |
2. Fix the data before resizing
redis-cli -h <endpoint> --tls --bigkeys # largest keys per type
redis-cli -h <endpoint> --tls --memkeys # memory per key sample
redis-cli -h <endpoint> --tls INFO keyspace # keys and keys with expiry
- Keys without TTL that should expire (sessions, temp results). Set TTLs in code.
- Huge values (whole serialised objects) that could be smaller or compressed.
- Hot keys hammered by every request. Local in-process cache for a few seconds helps.
3. Engine choice: Valkey
ElastiCache for Valkey is API-compatible with Redis OSS and priced lower than Redis OSS on ElastiCache (check current pricing in your region). Upgrading an existing Redis OSS cluster to Valkey is an in-place engine change on supported versions. Test client libraries and commands in non-prod first.
4. Node type and topology
| Finding | Action |
|---|---|
| Memory < 50% for weeks, CPU low | Smaller node type (online vertical scaling supported) |
| One shard hot, others idle | Fix key distribution (hash tags), not just add shards |
| Memory high, CPU fine | Larger memory node or more shards (cluster mode) |
| Read-heavy | Read replicas and client reads from replicas |
| Network allowance exceeded | Larger network-optimised node or more shards |
Current Graviton node types (e.g. r7g/m7g) give better price-performance than older generations.
aws elasticache modify-replication-group --replication-group-id sessions \
--cache-node-type cache.r7g.large --apply-immediately
Keep Multi-AZ with at least one replica for production caches that matter for availability.
5. Data tiering for large, mostly cold datasets
Data tiering node types (r6gd family) keep hot items in memory and move less-used items to local SSD. Good for large datasets where a small portion is frequently accessed and slightly higher latency for cold items is fine.
6. Serverless for variable load
ElastiCache Serverless scales capacity automatically and bills by data stored and processing units (ECPUs). Fits spiky or unpredictable workloads and small caches where node minimums waste money. For steady, large caches, right-sized nodes with reservations are usually cheaper. Compare with a month of metrics.
7. Commit and clean up
- Reserved nodes for steady, right-sized clusters (after right-sizing).
- Delete caches for retired apps; check old snapshots.
- Non-prod: smaller nodes, no replicas, or serverless.
Warning
Downsizing a cache with
noevictionpolicy can cause write errors when memory fills; withallkeys-lruit causes more misses and more database load. Check the eviction policy and database headroom before shrinking.
Checklist
- Memory, CPU, network, connections and hit rate reviewed
- TTLs, big keys and hot keys fixed
- Valkey evaluated
- Node type and shard/replica counts right-sized
- Data tiering or serverless where the pattern fits
- Reservations after sizing; unused caches removed