Provisioning ElastiCache normally means choosing a node type, a shard count, and a replica count - capacity decisions you make before you know the traffic. ElastiCache Serverless removes them. You call CreateServerlessCache, get back a single endpoint, and the service scales capacity up and down automatically as your workload changes. You pay for the data you store and the requests you run, not for nodes sitting idle.
This page provisions a serverless cache, discovers its endpoint, connects a TLS client, and explains when serverless wins over provisioned nodes.
Create the serverless cache, wait until it is available by polling its status, read the single endpoint, then connect with a TLS client. Serverless always encrypts in transit, so the client must use TLS. Adding CacheUsageLimits caps how much it can grow, bounding cost.
# --- Python (boto3) ---import boto3, timeec = boto3.client("elasticache", region_name="us-east-1")# 1. Create with optional caps on stored data and request compute.ec.create_serverless_cache( ServerlessCacheName="app-cache", Engine="valkey", SubnetIds=["subnet-aaa", "subnet-bbb"], SecurityGroupIds=["sg-0123456789abcdef0"], CacheUsageLimits={ "DataStorage": {"Maximum": 10, "Unit": "GB"}, "ECPUPerSecond": {"Maximum": 50000}, },)# 2. Poll until available (no dedicated waiter for serverless caches).while True: sc = ec.describe_serverless_caches(ServerlessCacheName="app-cache")["ServerlessCaches"][0] if sc["Status"] == "available": break time.sleep(10)endpoint = sc["Endpoint"]["Address"]print("connect to:", endpoint, sc["Endpoint"]["Port"])
// --- TypeScript (AWS SDK v3) ---import { ElastiCacheClient, CreateServerlessCacheCommand, DescribeServerlessCachesCommand,} from "@aws-sdk/client-elasticache";const ec = new ElastiCacheClient({ region: "us-east-1" });// 1. Create with optional caps on stored data and request compute.await ec.send(new CreateServerlessCacheCommand({ ServerlessCacheName: "app-cache", Engine: "valkey", SubnetIds: ["subnet-aaa", "subnet-bbb"], SecurityGroupIds: ["sg-0123456789abcdef0"], CacheUsageLimits: { DataStorage: { Maximum: 10, Unit: "GB" }, ECPUPerSecond: { Maximum: 50000 }, },}));// 2. Poll until available (no dedicated waiter for serverless caches).let sc;for (;;) { const out = await ec.send(new DescribeServerlessCachesCommand({ ServerlessCacheName: "app-cache" })); sc = out.ServerlessCaches![0]; if (sc.Status === "available") break; await new Promise((r) => setTimeout(r, 10000));}const endpoint = sc.Endpoint!.Address;console.log("connect to:", endpoint, sc.Endpoint!.Port);
Connect with a TLS Redis client (a cache client, not the AWS SDK):
# --- Python: redis-py (cache client, NOT the AWS SDK) ---import redis# Serverless always requires TLS; one endpoint handles reads and writes.r = redis.Redis(host=endpoint, port=6379, ssl=True, decode_responses=True)r.set("session:abc", "payload", ex=600)print(r.get("session:abc"))
// --- Node.js: ioredis (cache client, NOT the AWS SDK) ---import Redis from "ioredis";// Serverless always requires TLS; one endpoint handles reads and writes.const r = new Redis({ host: endpoint, port: 6379, tls: {} });await r.set("session:abc", "payload", "EX", 600);console.log(await r.get("session:abc"));
What this demonstrates:
CreateServerlessCache takes no CacheNodeType, NumNodeGroups, or NumCacheClusters - there is nothing to size.
Serverless exposes one endpoint for both reads and writes; there is no separate primary/reader to route between.
In-transit TLS is mandatory, so the client always connects with ssl=True / tls: {}.
CacheUsageLimits caps stored data and ECPUs, so a runaway workload cannot grow cost without bound.
Serverless removes every capacity decision: no node type, no shard count, no replica count, no auto-scaling policy. AWS manages the underlying nodes and shards, adds capacity within seconds as your traffic or data grows, and removes it when it shrinks. It runs across multiple Availability Zones by default for high availability.
Billing changes accordingly. Instead of paying per node-hour, you pay for two things: data stored, metered in GB-hours, and request compute, metered in ElastiCache Processing Units (ECPUs) - roughly, work proportional to the number and size of the commands your app runs. An idle serverless cache costs only its stored data (with a small minimum), which is why it is so attractive for dev/test and spiky workloads.
Serverless is the right default when you cannot forecast traffic: new features, launches, seasonal spikes, unpredictable batch jobs, and anything you do not want to babysit. It absorbs bursts automatically and costs little when quiet.
Provisioned nodes win when load is steady, high, and predictable. At sustained high utilization, a right-sized reserved node (especially with reserved-node pricing) is usually cheaper per unit of work than the ECPU-plus-storage model, because you are paying a flat rate for capacity you are actually keeping busy. The common lifecycle mirrors the DynamoDB one: launch serverless, watch usage for a few weeks, and move to provisioned nodes only once the traffic shape is clearly steady enough to justify it.
CacheUsageLimits is the guardrail. DataStorage.Maximum caps how much data the cache will hold, and ECPUPerSecond.Maximum caps request throughput. Past those caps the cache applies backpressure rather than scaling further, protecting you from a bug or a traffic anomaly turning into an unbounded bill. Set both to sane ceilings for the workload; you can raise them later with ModifyServerlessCache.
A serverless cache presents a single endpoint that serves reads and writes - there is no primary/reader split to manage, since scaling and topology are hidden. Encryption in transit is always on, so every client connects with TLS. Internally a serverless Redis/Valkey cache behaves like a cluster, so for very heavy multi-key workloads a cluster-aware client can help, but for typical GET/SET usage a standard TLS client against the endpoint is all you need.
Passing node parameters to CreateServerlessCache. There is no CacheNodeType or shard count. Fix: provision serverless with just engine, subnets, and security groups (plus optional limits).
Connecting without TLS. Serverless mandates in-transit encryption. Fix: always use ssl=True / tls: {} / rediss://.
Waiting with a non-existent waiter. Serverless caches have no dedicated available waiter. Fix: poll DescribeServerlessCaches until Status is available.
Assuming serverless is always cheapest. At steady high load, reserved nodes usually beat ECPU-plus-storage. Fix: measure usage, then decide between serverless and provisioned.
No usage caps set. Without CacheUsageLimits, a runaway workload scales cost freely. Fix: set DataStorage and ECPUPerSecond maximums as guardrails.
Expecting a reader endpoint. Serverless exposes one endpoint only. Fix: send both reads and writes to that single endpoint.
Every capacity decision - node type, shard count, replica count, and scaling policy. You provide an engine, subnets, and security groups; AWS manages the nodes and scales capacity automatically within seconds as data and traffic change.
How is serverless billed?
By data stored (GB-hours) plus request compute measured in ElastiCache Processing Units (ECPUs), rather than per node-hour. An idle serverless cache costs only its stored data with a small minimum, which suits spiky and dev/test workloads.
Which SDK call creates a serverless cache?
CreateServerlessCache. It takes no CacheNodeType, NumNodeGroups, or NumCacheClusters - just the engine, subnet IDs, security groups, and optional CacheUsageLimits. Passing node parameters is a common mistake.
How do I wait for it to be ready?
Poll DescribeServerlessCaches until Status is available - serverless caches do not have a dedicated waiter like replication groups and cache clusters do. Sleep briefly between polls to avoid tight looping.
Does serverless require TLS?
Yes. Encryption in transit is always on for serverless caches, so every client must connect with TLS - ssl=True in redis-py, tls: {} in ioredis, or a rediss:// URL. A plaintext connection will fail.
When should I choose provisioned over serverless?
When load is steady, high, and predictable. At sustained high utilization a right-sized reserved node usually costs less than the ECPU-plus-storage model. Launch on serverless, measure for a few weeks, then switch if the traffic is clearly steady.
How do I cap serverless cost?
Set CacheUsageLimits with DataStorage.Maximum and ECPUPerSecond.Maximum. Beyond those ceilings the cache applies backpressure instead of scaling further, protecting you from a bug or traffic anomaly running up an unbounded bill. Raise the limits later if needed.
Does serverless have primary and reader endpoints?
No. It exposes a single endpoint that handles both reads and writes, because scaling and topology are managed for you. Send all traffic to that one endpoint rather than routing between a primary and a reader.