This page is the working quickstart for ElastiCache: provision a small Redis (or Valkey) cache with the AWS SDK, find the endpoint the SDK reports, and connect to it from application code. The one idea to keep straight throughout is the split introduced in the previous page - the AWS SDK provisions the cache; a Redis client uses it.
Each example is small. Read them in order: create the replication group, wait for it, discover its endpoints, then connect and run SET/GET with a cache client. The AWS SDK snippets use CodeGroup; the connection snippets are plain fences because a Redis client is not the AWS SDK.
Credentials configured via aws configure, environment variables, or an IAM role - the SDK resolves them automatically.
A VPC with a cache subnet group and a security group that allows TCP 6379 from your application. ElastiCache is only reachable from inside its VPC, never the public internet.
A region set with AWS_REGION or passed per client. These examples assume us-east-1.
Create a two-node Redis replication group: one primary plus one replica, with encryption on. NumCacheClusters: 2 means one writer and one reader - this is non-cluster (single-shard) mode, which is the right default until you need sharding.
Now leave the AWS SDK behind. The snippets below use a Redis client library - redis-py in Python, ioredis in JavaScript - pointed at the endpoint the SDK reported. Because the group was created with in-transit encryption, the connection uses TLS.
# --- Python: redis-py (cache client, NOT the AWS SDK) ---import redis# Point at the PRIMARY endpoint for writes; rediss:// because TLS is on.r = redis.Redis(host=primary, port=6379, ssl=True, decode_responses=True)r.set("user:1", "Ada", ex=300) # SET with a 300s TTLprint(r.get("user:1")) # -> "Ada" (a cache hit)
// --- Node.js: ioredis (cache client, NOT the AWS SDK) ---import Redis from "ioredis";// tls:{} enables encryption in transit; host is the PRIMARY endpoint.const r = new Redis({ host: primary, port: 6379, tls: {} });await r.set("user:1", "Ada", "EX", 300); // SET with a 300s TTLconsole.log(await r.get("user:1")); // -> "Ada" (a cache hit)
These are third-party clients speaking the Redis wire protocol - AWS does not ship them and the AWS SDK does not wrap them.
ex=300 / "EX", 300 attach a TTL so the entry self-expires after five minutes.
Use the reader endpoint for read-only clients to spread reads across replicas.
decode_responses=True (redis-py) returns strings instead of bytes; omit it if you store binary.
Put the pieces together into the read loop that motivates the whole service: check the cache, fall back to the database on a miss, and populate the cache for next time.
# --- Python: redis-py + your DB (cache client, NOT the AWS SDK) ---def get_user(user_id: str) -> str: key = f"user:{user_id}" cached = r.get(key) if cached is not None: return cached # cache hit row = db_fetch_user(user_id) # cache miss -> backing store r.set(key, row, ex=300) # populate for next time return row
// --- Node.js: ioredis + your DB (cache client, NOT the AWS SDK) ---async function getUser(userId) { const key = `user:${userId}`; const cached = await r.get(key); if (cached !== null) return cached; // cache hit const row = await dbFetchUser(userId); // cache miss -> backing store await r.set(key, row, "EX", 300); // populate for next time return row;}
The first call for a key misses and reads the database; subsequent calls hit for the TTL window.
The database is untouched on a hit - this is exactly how a cache sheds read load.
The code must be correct with a cold, empty cache - every miss simply costs one database read.
The full pattern, including write-through and invalidation, has its own page.
Everything on this page falls into one of two buckets. The AWS SDK (create_replication_group, waiters, describe_replication_groups) is the control plane: it stands the cache up and tells you where it lives. The Redis client (redis.Redis, new Redis) is the data plane: it moves keys and values. You provision once, at deploy time, with the AWS SDK; you read and write thousands of times per second with the Redis client. Keeping these separate in your head prevents the most common beginner confusion - looking for a get_item on the ElastiCache SDK client that does not exist.
The primary and reader endpoints are DNS names managed by AWS, not fixed IPs. When AutomaticFailoverEnabled promotes a replica after a primary failure, AWS repoints the primary endpoint DNS at the new primary. Your client keeps using the same hostname and reconnects. This is why you configure clients with endpoints, never with node addresses - the indirection is the failover mechanism.
Creating the group with TransitEncryptionEnabled=True means every client must use TLS: ssl=True in redis-py, tls: {} in ioredis, or a rediss:// URL. Forgetting this yields a connection that hangs or is refused. If you also set AuthToken (a password) or use IAM authentication, the client must supply that credential too.
Calling the SDK to read a key. There is no get/set on the ElastiCache SDK client. Fix: provision with the AWS SDK, then read and write with a Redis client library.
Connecting before available. The endpoint DNS may not resolve during creation. Fix: block on the replication_group_available waiter first.
Plaintext client against a TLS cache. With TransitEncryptionEnabled=True, a redis:// client hangs or is refused. Fix: use ssl=True / tls: {} / rediss://.
Trying to reach the cache from your laptop. ElastiCache lives in a VPC with no public endpoint. Fix: run the client inside the VPC (EC2, Lambda in-VPC, ECS) or tunnel through a bastion.
Hard-coding a node IP. IPs change on failover and replacement. Fix: always connect to the primary/reader endpoint DNS names from DescribeReplicationGroups.
No TTL on cached entries. Without ex/EX, entries live until evicted and can serve stale data indefinitely. Fix: set a deliberate TTL on writes.
CreateReplicationGroup creates a Redis or Valkey cache (one primary plus optional replicas). CreateCacheCluster is the Memcached call. For anything Redis/Valkey, reach for the replication group API even for a single node.
How do I actually read and write cached values?
With a Redis client library - redis-py in Python, ioredis or node-redis in JavaScript - pointed at the endpoint the SDK reports. The AWS SDK provisions and describes the cache but never runs GET or SET.
Why can't I connect from my local machine?
ElastiCache has no public endpoint; it is reachable only from inside its VPC. Run your client on an EC2 instance, an in-VPC Lambda, or an ECS task in the same VPC, or tunnel through a bastion host for testing.
Do I use the primary or the reader endpoint?
Send writes to the primary endpoint and reads to the reader endpoint. The reader load-balances across replicas, so routing reads there scales read throughput without changing application logic. Both survive failover as stable DNS names.
What does TransitEncryptionEnabled require on the client?
TLS. Set ssl=True in redis-py, tls: {} in ioredis, or use a rediss:// URL. If you also enabled an AuthToken or IAM auth, the client must supply that credential as well, or the connection is rejected.
How long does creation take?
Usually several minutes for a Redis replication group. Block on the replication_group_available waiter (with a generous max wait) rather than sleeping a fixed time, and only connect once it returns available.
What is NumCacheClusters versus NumNodeGroups?
NumCacheClusters sets the number of nodes in a single-shard group (1 primary plus replicas). NumNodeGroups sets the number of shards for cluster mode. Use NumCacheClusters for a simple cache; see the cluster-mode page for sharding.
Should every cached entry have a TTL?
Almost always. A TTL bounds staleness and lets cold keys expire so memory stays available for hot ones. Omit it only for data you invalidate explicitly, and even then a safety TTL is good insurance against leaks.