The dev team is about to flip a feature flag that changes the shape of cached objects in production Redis. The fallback plan is “if anything goes wrong, we restore the cluster from the daily snapshot at 04:00.” Nobody has actually tested the restore. The on-call engineer asks the right question — “what does restore actually do?” — and gets a vague answer. The real answer is that ElastiCache restores by creating a new cluster from the snapshot. It does not overwrite the existing one. It also takes 15–60 minutes depending on cluster size. The fallback plan as written would have caused more downtime than the failure mode it was protecting against. Here is what backups actually do.
What’s happening
ElastiCache snapshots are point-in-time backups of the Redis dataset to S3 (in an AWS-managed bucket, not a customer bucket — they are exposed through the ElastiCache API, not S3 directly). Snapshots are taken via Redis’s BGSAVE mechanism — a fork of the main process writes the RDB file in the background while the cluster keeps serving traffic. Read performance is unaffected; write latency may briefly tick up during the fork on memory-pressure-heavy nodes.
Three knobs control how snapshots happen.
SnapshotRetentionLimit is the number of automatic daily snapshots ElastiCache keeps. Values from 0 to 35. Setting it to 0 disables automatic snapshots entirely. Setting it to 7 keeps a week of rolling daily snapshots. Setting it to 35 keeps the maximum 35-day window. There is no built-in option for hourly automatic snapshots — daily is the granularity.
SnapshotWindow is the 60-minute window each day when the automatic snapshot runs. Pick a window during low write traffic — the fork is cheaper when memory is stable. The window is in UTC. A 03:00–04:00 UTC window is 22:00–23:00 EST.
Manual snapshots are user-initiated and have no count limit (beyond AWS account quotas, typically generous). Manual snapshots survive cluster deletion — if you delete the cluster, the automatic snapshots go with it, but manual snapshots stay until you delete them explicitly. This is the “take a snapshot before you do something risky” pattern.
Restore is the part that surprises people. There is no in-place restore. The restore API takes a snapshot and creates a new cluster from it. The new cluster has a different endpoint. Application config must change to point at the new cluster, or you must repoint via DNS. The old cluster is untouched. You can delete the old cluster after the restore is verified, but that is a separate step.
What snapshots cover and what they do not. Snapshots are RDB-format dumps — every key, every value, every TTL — captured at the moment of BGSAVE. They do not capture in-flight writes happening between the start of BGSAVE and its completion (those writes go into the new cluster only when you re-run the workload against it). They do not capture Redis configuration that lives in the parameter group — that follows the cluster, not the snapshot. They do not capture VPC, subnet group, or security group settings — those are properties of the cluster object, not the data.
Why “restart with empty cache” is sometimes safer. If the cluster is corrupted because of a bad write pattern (a buggy deploy wrote objects with the wrong schema; an attacker poisoned the cache; a manual FLUSHALL ran in production), restoring from yesterday’s snapshot brings back the bad state as it existed at 04:00 — possibly including the same corruption if it happened before 04:00. The clean alternative is to delete the cluster, create a new empty one, and let the application rebuild the cache on first access. The first few minutes are slow (cache miss storm), but the cache is provably clean. This is often the right call after a corruption event.
How to verify
Three commands tell you what backups exist and whether they are usable.
List automatic and manual snapshots.
aws elasticache describe-snapshots \
--replication-group-id saas-prod \
--query 'Snapshots[].[SnapshotName,SnapshotStatus,SnapshotSource,NodeSnapshots[0].SnapshotCreateTime]' \
--output table
The output shows snapshot name (system-generated for automatic, user-provided for manual), status (available, creating, deleting), source (automated or manual), and the actual creation time. Verify three things: the count matches your SnapshotRetentionLimit, the most recent automatic snapshot is from within the last 24 hours, and any pre-change manual snapshots are still present.
Check the snapshot window and retention.
aws elasticache describe-replication-groups \
--replication-group-id saas-prod \
--query 'ReplicationGroups[].[ReplicationGroupId,SnapshotWindow,SnapshotRetentionLimit]' \
--output table
A production cluster should have SnapshotRetentionLimit of at least 7. A cluster with 0 is silently uninsured — there are no automatic snapshots and the team probably does not realize it.
Test a restore in a non-production account. The only way to know a restore works is to do one. Pick a recent snapshot, restore it to a new cluster name, connect to the new cluster, verify a few keys are present:
aws elasticache create-replication-group \
--replication-group-id saas-prod-restore-test \
--replication-group-description "Restore test" \
--snapshot-name saas-prod-2026-05-25-04-00 \
--cache-node-type cache.r6g.xlarge \
--num-cache-clusters 2 \
--automatic-failover-enabled
Wait for it to become available (10–60 minutes depending on snapshot size), then connect via the new endpoint:
redis-cli -h saas-prod-restore-test.abc123.ng.0001.use1.cache.amazonaws.com PING
redis-cli -h saas-prod-restore-test.abc123.ng.0001.use1.cache.amazonaws.com DBSIZE
redis-cli -h saas-prod-restore-test.abc123.ng.0001.use1.cache.amazonaws.com KEYS 'sess:*' | head -5
DBSIZE should match the approximate count from the source cluster at snapshot time. Then delete the test cluster to avoid leaving an idle resource running.
The fix
The operational pattern that works for ElastiCache backups.
Step 1: set retention to 7–14 days for production clusters. The default is 0 on creation via some paths. Production clusters need automatic snapshots. Anything less than 7 days leaves no margin for “we discovered the corruption two days later.”
aws elasticache modify-replication-group \
--replication-group-id saas-prod \
--snapshot-retention-limit 14 \
--snapshot-window 03:00-04:00 \
--apply-immediately
The change applies on the next snapshot window. Existing snapshots are retained according to the new limit going forward.
Step 2: take a manual snapshot before any risky change. “Risky” includes: parameter-group changes, engine version upgrades, scaling operations, schema changes in cached objects, any feature flag flip that affects what is written to cache.
aws elasticache create-snapshot \
--replication-group-id saas-prod \
--snapshot-name saas-prod-pre-feature-flag-2026-05-26
The snapshot creation runs asynchronously. Wait for SnapshotStatus to be available before proceeding with the change. Manual snapshots survive cluster deletion, so they also serve as the “before we deleted this cluster” archive.
Step 3: document the restore plan. Every snapshot is useless without a known path to use it. The plan must include: which snapshot to restore (today’s automatic, or the pre-change manual), the new cluster name pattern, the parameter group and subnet group that should be applied, and how the application config is repointed (Route 53 CNAME swap, environment variable update with deploy, etc.). Test the plan in staging before relying on it in production.
Step 4: decide upfront whether corruption restores or rebuilds. For each cluster, decide: if the cache is corrupted, do we restore from snapshot, or do we rebuild from empty? The decision depends on what the cache holds.
- Sessions: usually rebuild (users re-authenticate; minor inconvenience).
- Computed responses with a source of truth in the database: usually rebuild (the cache miss storm is brief; the data is verifiably clean).
- Rate limit counters: usually rebuild (the worst case is a brief window of higher allowed rates).
- Authoritative state that does not exist anywhere else (rare in Redis but happens): restore from snapshot, with the understanding that data between snapshot and corruption is lost.
The pre-decided pattern saves time during the actual incident. The on-call engineer who has already thought “we rebuild this from empty” does not waste 40 minutes restoring a snapshot they were going to discard anyway.
Step 5: clean up old test restores. Restore tests leave clusters running. They are not cheap. Build the test into the runbook with a cleanup step at the end — the restore is verified by listing 100 keys, querying a few values, and confirming DBSIZE. The verification takes minutes. The cleanup takes one API call.
aws elasticache delete-replication-group \
--replication-group-id saas-prod-restore-test
The frame to carry: snapshots are insurance, not a magic undo button. The restore takes time, creates a new cluster, requires a config repoint, and sometimes brings back the same problem you were trying to escape. The disciplined version of “we have backups” is: automatic snapshots configured with sane retention, manual snapshots before any risky change, a documented and tested restore path, and a pre-decided answer to “restore or rebuild” for each cluster role.
Stack Harbor designs Redis topologies as part of cluster-tier work in Managed AWS and the HA Clusters operating layer. If your cluster’s backup plan is “we’ll figure it out if it happens,” start with an infrastructure consult.