AWS Redis (ElastiCache): Setup and Best Practices
Amazon ElastiCache for Redis is AWS's managed Redis service. It handles provisioning, patching, replication, and failover so you don't have to run Redis on EC2 yourself. You get a Redis endpoint and AWS takes care of the infrastructure underneath.
The main reason it exists: running Redis yourself on EC2 means you're responsible for OS updates, replication setup, failure detection, and node replacement. ElastiCache offloads all of that.
Valkey or Redis OSS
ElastiCache now runs three engines: Valkey, Redis OSS, and Memcached. Per the ElastiCache engine versions page, Redis OSS support stops at version 7.1, while Valkey, the Linux Foundation fork of Redis 7.2, is at 9.1. Valkey is a drop-in replacement for Redis OSS clients, and AWS lets you upgrade an existing Redis OSS cluster to Valkey in place.
For a new cache, Valkey is the better default on ElastiCache. It is where new features land (vector search, full-text search, and optional durability), and AWS prices it 20% lower than Redis OSS on nodes and 33% lower on Serverless. Older Redis OSS versions are also moving to paid Extended Support: v4 and v5 left standard support on January 31, 2026, and v6 follows on January 31, 2027.
Everything below applies to both engines unless noted. Clients and commands are the same.
Two deployment modes
ElastiCache offers two ways to run Redis: Serverless and a self-managed cluster.
ElastiCache Serverless
Serverless is the simpler option. You create a cache and AWS handles scaling, replication, and capacity automatically. There are no nodes to size, no shards to configure, and no cluster topology to manage.
You pay for what you use: data stored (per GB-hour) and ElastiCache Processing Units (ECPUs), which measure the vCPU time and data transferred by each request. It scales up and down without intervention, but it does not scale to zero. Each cache is billed for a minimum of 100 MB of data on Valkey and 1 GB on Redis OSS.
Serverless works well for variable workloads, development environments, or cases where you want minimal configuration. The trade-off is less control and potentially higher costs at consistent high load compared to right-sized provisioned nodes.
Self-managed cluster
The traditional mode gives you control over node type, shard count, replica count, and cluster topology. Current-generation choices include the Graviton-based cache.r8g, cache.r7g, cache.m8g, cache.m7g, and cache.t4g families. Larger nodes mean more memory and more throughput.
This mode is better for predictable production workloads where you want to optimize cost, or when you need specific configurations like particular instance sizes or reserved instance pricing.
Cluster mode disabled vs. cluster mode enabled
Within the self-managed path, you choose between two cluster configurations.
Cluster mode disabled gives you a single shard with one primary node and up to 5 read replicas. All writes go to the primary, all reads can be distributed across replicas. This is the simpler option: a single endpoint for writes, an optional reader endpoint for reads.
Cluster mode enabled partitions your keyspace across multiple shards (up to 500). Each shard has its own primary and replicas. This lets you scale beyond the memory and throughput limits of a single node.
The trade-off with cluster mode is operational complexity. Multi-key commands (MGET, MSET) and transactions only work when all keys map to the same shard. You can use hash tags ({user}.session and {user}.profile always land on the same shard) to work around this, but it requires thought upfront.
For most applications, cluster mode disabled is enough. Use cluster mode when your dataset exceeds the memory of your largest available node (about 505 GiB for cache.r8g.16xlarge, or 419 GiB for cache.r7g.16xlarge).
| Cluster mode disabled | Cluster mode enabled | |
|---|---|---|
| Shards | 1 | 1-500 |
| Max memory | Single node limit | Up to 500x node limit |
| Multi-key commands | Full support | Same shard only |
| Online resharding | No | Yes |
| Failover | Automatic (replica promotes) | Automatic per shard |
Creating a cluster
Via the AWS console
- Go to ElastiCache in the AWS console and click Create cluster
- Select Valkey or Redis OSS as the engine
- Choose Serverless or Design your own cache
- Set a name, description, and engine version
- Choose your node type and number of replicas
- Select your VPC and subnets
- Assign a security group
- Configure backups, maintenance window, and encryption settings
- Click Create
Via the AWS CLI
This creates a primary with one replica, encryption at rest and in transit, and automatic failover enabled. For Valkey, use --engine valkey and a Valkey version such as 8.2. Run aws elasticache describe-cache-engine-versions --engine valkey to list the versions available in your region.
To create the subnet group first (required if you don't have one):
VPC and security group configuration
ElastiCache nodes are not publicly accessible. They must run inside a VPC and can only be reached by resources in the same VPC (or connected VPCs via peering or Transit Gateway). The one exception is ElastiCache Serverless on Valkey 9.0 and later, which can expose a public endpoint that requires IAM authentication and TLS 1.3.
Your security group needs an inbound rule allowing TCP on port 6379 from your application's security group (not from 0.0.0.0/0). The recommended approach:
Referencing the app security group ID instead of a CIDR range means you don't need to update the rule when your application scales or its IP changes.
For the subnet group, include subnets from at least two availability zones. ElastiCache will place replicas across AZs automatically when Multi-AZ is enabled.
Connecting to your cache
ElastiCache provides a primary endpoint for writes and (when replicas exist) a reader endpoint for reads.
Example endpoints:
Connecting from Node.js
Connecting from Python
For cluster mode enabled, use a cluster-aware client. In redis-py 4.1 and later, cluster support is built in:
Work With Your Databases Like A Pro
Query, explore, and manage your databases with a beautiful desktop app and built-in AI.
Download Now
Multi-AZ and automatic failover
Enable --automatic-failover-enabled (and --multi-az-enabled) when creating your cluster. With these on, ElastiCache monitors the primary node and promotes a replica to primary if the primary becomes unavailable.
Failover typically completes in 60-90 seconds. DNS is updated to point to the new primary. Your application should handle connection retries with backoff to reconnect after failover.
One important detail: automatic failover requires at least one replica. A standalone primary (no replicas) cannot fail over.
For cluster mode enabled, each shard fails over independently. A single-shard failure doesn't affect other shards.
Cost considerations
ElastiCache pricing has several components. The figures below are us-east-1 on-demand rates from the ElastiCache pricing page as of September 2026. Check it for your region before you budget.
Node hours. Charged per hour for each running node. A cache.r7g.large (2 vCPU, 13 GiB) costs $0.219/hr on Redis OSS (about $160/month) and $0.1752/hr on Valkey (about $128/month). With one replica, double it.
Backup storage. Snapshot storage is billed at $0.085 per GiB-month. Creating a backup or restoring from one has no data transfer fee.
Data transfer. Traffic within the same AZ is free. ElastiCache does not charge for cross-AZ traffic in or out of the node, but the EC2 side pays standard inter-AZ data transfer rates. This adds up when your application and cache are in different AZs.
Serverless pricing. Valkey costs $0.084 per GB-hour of data stored and $0.0023 per million ECPUs. Redis OSS costs $0.125 per GB-hour and $0.0034 per million ECPUs. Storage dominates for most caches: 10 GB held for a full month is about $613 on Valkey and about $913 on Redis OSS before any request charges.
To reduce cost on steady workloads, consider reserved nodes. AWS quotes discounts of up to 55% over on-demand rates, depending on term and payment option.
Best practices
Set a maxmemory policy
ElastiCache nodes have fixed memory. When the cache fills up, Redis needs to know what to do. Configure this in your parameter group:
allkeys-lru evicts the least recently used keys across all keys. This is the most common choice for pure caching workloads. If you're using Redis for both caching and persistent data (like session storage), volatile-lru only evicts keys that have a TTL set, leaving persistent keys alone.
Avoid noeviction unless you want Redis to return errors when memory is full. That will break your application in unexpected ways.
Set an explicit maxmemory value
Even though the node has a fixed amount of RAM, some memory is used by Redis's own overhead, replication buffers, and OS processes. A safe rule is to set maxmemory to 75-80% of the node's available memory. For a 13 GB node:
This prevents Redis from running out of memory for replication buffers, which can cause connection drops.
Use connection pooling
Opening a new connection to Redis on every request is expensive. Use a connection pool in your application.
Size your pool based on the number of application threads or concurrent requests. Too small and requests queue up waiting for a connection. Too large and you'll hit ElastiCache's connection limit (visible in CloudWatch as CurrConnections).
Always set TTLs
Keys without TTLs never expire. In a cache, this means the dataset grows until eviction kicks in and removes keys you might still want. Set expiration on every key you write:
Monitor with CloudWatch
ElastiCache publishes metrics to CloudWatch automatically. The most important ones to watch:
| Metric | What it tells you |
|---|---|
CacheHits / CacheMisses | Cache effectiveness. Low hit rate means data isn't being cached long enough or keys are evicted too early. |
CurrConnections | Current client connections. Watch for spikes or sustained high values. |
DatabaseMemoryUsagePercentage | How full the cache is. Set an alarm at 80%. |
Evictions | Keys being evicted. High evictions mean the cache is too small for the working set. |
ReplicationLag | How far behind replicas are. High lag means replicas may serve stale data. |
EngineCPUUtilization | CPU usage on the Redis engine thread. Sustained high values indicate command bottlenecks. |
Set CloudWatch alarms on DatabaseMemoryUsagePercentage (alert at 80%) and Evictions (alert on sustained high values). These are the two most common production issues.
ElastiCache vs. self-hosted Redis vs. Upstash
ElastiCache is not the only option for managed Redis. Here's how it compares:
| ElastiCache | Self-hosted on EC2 | Upstash | |
|---|---|---|---|
| Setup time | Minutes | Hours to days | Minutes |
| Management overhead | Low | High | Minimal |
| Pricing model | Per node-hour, or data stored plus ECPUs on Serverless | EC2 + EBS costs | Per request |
| Minimum cost | About $6/mo (Valkey Serverless) or $9/mo (Valkey cache.t4g.micro) | EC2 instance cost | $0 (free tier) |
| Scale to zero | No (Serverless: no) | No | Yes |
| Multi-region | Via Global Datastore | Manual setup | Yes (built-in) |
| VPC support | Yes | Yes | Via private link |
| AWS integration | Native | Manual | Limited |
| Max data size | Node memory | Node memory | 256 MB free, 100 GB pay-as-you-go |
Choose ElastiCache when you're already running on AWS, need tight VPC integration, and want a managed service without thinking about pricing per request. It's the right default for production workloads on AWS.
Choose self-hosted Redis when you need full control over Redis configuration, want to run a specific version or fork, or your team has the operational capacity to manage it. Cost savings are real only if you're running at high utilization.
Choose Upstash when your workload is intermittent, you're building a side project, or you need a Redis-compatible store with a free tier and per-request pricing. Upstash also works well outside AWS (Vercel, Cloudflare Workers, etc.).
For most teams shipping on AWS, ElastiCache is the straightforward choice. Serverless is worth considering for variable or low-traffic workloads. For steady, high-throughput production use, provisioned nodes with reserved pricing are more cost-effective.
Keep Reading
Redis vs Kafka: Streams, Queues, and When to Use Each
Redis vs Kafka compared for event streaming, job queues, consumer groups, retention, replay, and operations, with Redis Streams and Kafka demos run side by side.
Redis Alternatives: Valkey, Dragonfly, KeyDB, Garnet, and Memcached
The best Redis alternatives compared by compatibility, licensing, persistence, clustering, and performance, with a practical migration checklist.
How to Fix Slow Redis Queries
A practitioner's guide to diagnosing and fixing slow Redis workloads. Why Redis slowness is fundamentally different from SQL, the big-key and hot-key problems, SLOWLOG and LATENCY, picking the right data structure, and the configuration that prevents outages.