/user/kayd @ devops :~$ cat valkey-aws-elasticache-guide.md

Valkey on AWS ElastiCache: A Hands-On Guide Valkey on AWS ElastiCache: A Hands-On Guide

QR Code linking to: Valkey on AWS ElastiCache: A Hands-On Guide
Karandeep Singh
Karandeep Singh
• 11 minutes

Summary

A start-to-finish walkthrough of running Valkey on AWS ElastiCache, built from a real hands-on session, complete with the security-group mistake, the TLS surprise, and a small health-check script.

I finally sat down and ran Valkey on AWS ElastiCache end to end, from an empty console to a working health-check script, and took notes on every wrong turn. This is that walkthrough. If you have ever wondered how to stand up a managed Valkey cache, reach it from your own code, and test it properly, this guide covers the whole path, including the two or three things that quietly go wrong the first time.

Valkey on AWS ElastiCache is worth knowing because Valkey is the open-source, community-run fork of Redis (now under the Linux Foundation), and AWS made it a first-class ElastiCache engine at a lower price than the Redis OSS option. You get an in-memory data store for caching, sessions, queues, and rate limiting, without running the servers yourself. I did this on a single tiny node so the whole exercise cost pennies.

Why Valkey on AWS, and what it costs

Valkey speaks the same protocol as Redis, so your existing clients and commands (SET, GET, DEL, TTL) all work unchanged. On ElastiCache you pick between Serverless (fastest to start, TLS always on, a floor around $6/month) and a node-based cluster where you choose the server size and pay per hour.

For a demo, the node-based path is cheaper and clearer. I used a single cache.t4g.micro node, which runs at roughly $0.016 per hour, about $0.40 for a full day. The golden rule that keeps this a pennies exercise: delete everything the same day. Leaving that node running all month is around $11 to $12.

Valkey, Redis, or Memcached?

ElastiCache actually offers three engines, and if you are new to caching it helps to know what each one is:

  • Redis OSS is a hugely popular in-memory data store. It is more than a cache: alongside simple GET/SET it gives you real data structures (lists, hashes, sets, sorted sets, streams), optional persistence to disk, replication, and pub/sub messaging. In early 2024 Redis changed its license to terms that are no longer open source.
  • Valkey is the community’s answer to that license change: a fork of Redis 7.2, kept open source under the Linux Foundation and backed by AWS, Google, Oracle, and others. It speaks the same protocol and commands as Redis, so it is a drop-in replacement, and AWS prices it about 20% cheaper than Redis OSS. That is why I reached for Valkey here.
  • Memcached is the old-timer: a bare-bones, multi-threaded cache that stores plain key/value pairs and nothing more. No data structures, no persistence, no replication. It is fast and simple, and still a fine choice when all you need is a big, plain cache in front of a database.

Rule of thumb: choose Valkey (or Redis) when you want data structures, persistence, or replication, which covers most real applications. Choose Memcached only when you want the simplest possible key/value cache and nothing more.

Serverless or a node-based cluster?

Whichever engine you pick, ElastiCache asks how you want to run it. The two options bill and scale very differently:

ServerlessNode-based cluster
CapacityScales automatically and instantlyYou choose node type and count
BillingData stored (GB-hours) + requests (ECPUs), ~$6/month floorPer node, per hour
Best forSpiky or unpredictable traffic; getting started fast; not managing capacitySteady, predictable load; fine-grained control; cost tuning with reserved nodes
TLSAlways onOptional (you choose at creation)
Cheapest small footprintNo (that ~$6 floor)Yes (a cache.t4g.micro is pennies a day)

For production with bursty traffic and nobody to babysit capacity, Serverless is the easy win: it scales up and down on its own and you never size a node. For a steady workload, a specific instance type, or a cost-controlled demo like this one, a node-based cluster wins. I chose node-based purely because a single tiny node is the cheapest way to learn.

Step 1: Create the security group first

A Valkey cache lives inside a VPC and sits behind a security group, which is just a firewall. I created that first so the cache and the client machine could share it.

In EC2 → Security Groups → Create security group, I made valkey-demo-sg in the default VPC and added one inbound rule: Custom TCP, port 6379, source = the same security group. That self-referencing rule is a clean pattern: anything wearing this security group is allowed to talk to anything else wearing it, no IP addresses to manage.

Security group inbound rule allowing TCP port 6379 from the same security group

Step 2: Launch an EC2 client in the same VPC

Here is the first thing people miss: ElastiCache is only reachable from inside its VPC. You cannot connect from your laptop. You need a small machine in the same network to run your client from.

I launched a t3a.micro EC2 instance named valkey-demo-client (Ubuntu, though Amazon Linux works just as well), enabled a public IP, and, importantly, attached both the SSH security group and valkey-demo-sg. That second group is what will later let the box reach the cache.

EC2 instance security tab showing both valkey-demo-sg and the launch-wizard security group attached

Step 3: Create the Valkey cache

Back in ElastiCache → Valkey caches → Create, I chose Design your own cache → node-based cluster. One warning: the wizard defaults the Configuration preset to a large Production node (an r7g.xlarge, hundreds of dollars a month). I switched the creation method to full control and set:

  • Node type: cache.t4g.micro
  • Replicas: 0
  • Name: valkey-demo

The ElastiCache create-cache wizard with the Valkey engine and a node-based cluster selected, showing the Demo cache.t4g.micro configuration option

It sat in Creating for about seven minutes, then flipped to Available with a configuration endpoint like clustercfg.valkey-demo.xxxxxx.use1.cache.amazonaws.com:6379.

ElastiCache cluster details page showing status Available, node type cache.t4g.micro, and the configuration endpoint

Two settings landed differently than I expected, and both are locked at creation time, so plan for them:

  • Cluster mode was Enabled. That is fine; you connect via the configuration endpoint and good client libraries handle the topology automatically.
  • Encryption in transit was Required. This means every client must speak TLS. It is one extra flag, and it matches how you would really run this, so I left it.

Step 4: The connection that hung, and why

With the cache Available, I connected to the EC2 box, installed the Valkey Python client in a virtual environment, and wrote the smallest possible program: connect and PING. It hung, then failed:

valkey.exceptions.ValkeyClusterException: Valkey Cluster cannot be connected.
Please provide at least one reachable node: Timeout connecting to server

A timeout, not a rejection, is the classic signature of a network block, not a code bug. I checked the cache’s security group and found the problem immediately: the create wizard had put the cache on the VPC default security group, not on valkey-demo-sg. My EC2 client wore valkey-demo-sg, so it was never allowed in on port 6379.

ElastiCache connectivity tab showing the cache attached to the default security group instead of valkey-demo-sg

The fix took thirty seconds: Modify the cache, add valkey-demo-sg, and remove default.

ElastiCache security groups after the fix, showing valkey-demo-sg added alongside the default group

Because that group already allowed 6379 from itself, and the client was a member, the very next run connected:

cache says: True

Step 5: Test with valkey-cli, the tool you already have

I did not need to write a program to poke at the cache. Valkey ships valkey-cli, its own command-line client. On Ubuntu I installed it with sudo apt-get install -y valkey-tools and connected with the two flags this cache requires:

valkey-cli -h clustercfg.valkey-demo.xxxxxx.use1.cache.amazonaws.com -p 6379 --tls -c

The --tls flag is mandatory here (encryption in transit is Required), and -c turns on cluster mode so the CLI follows the cache’s “that key lives on another shard” redirects. From there it is plain Valkey:

> SET region us-east-1
OK
> GET region
"us-east-1"
> SET version v2.0.1 EX 300
OK
> KEYS *
1) "version"
2) "region"
> DEL region
(integer) 1

Two things bit me here, and both are good to know:

  • Keys are case-sensitive. GET REGION returned (nil), while GET region returned the value. They are two different keys.
  • TTL really auto-expires. A key I set with EX 10 vanished from KEYS * on its own after ten seconds. To check the time left from inside the CLI, use TTL keyname (it returns seconds remaining, -1 for no expiry, or -2 if the key is already gone). Note that sleep is a shell command, not a Valkey one, so the cache rejects it.

If you want a fast refresher on the shell side of this, my Ubuntu Terminal cheatsheet and Amazon Linux 2 Terminal cheatsheet cover the apt/yum and systemd commands I leaned on.

Step 6: When to reach for a script instead

The CLI is perfect for poking around. A script earns its place only when you need something repeatable that the CLI is clumsy at. For me that was a health check: connect, write a canary value, read it straight back, and confirm they match, the kind of probe a monitor or cron job runs on a schedule.

I built it up one piece at a time in Python. The core is small:

import time
from valkey.cluster import ValkeyCluster

ENDPOINT = "clustercfg.valkey-demo.xxxxxx.use1.cache.amazonaws.com"

client = ValkeyCluster(host=ENDPOINT, port=6379, ssl=True, decode_responses=True)

# write a unique canary value, then read it back and compare
token = str(time.time())
client.set("healthcheck:canary", token, ex=30)
got = client.get("healthcheck:canary")

if got == token:
    print("OK: cache is healthy (write + read matched)")
else:
    print(f"FAIL: expected {token}, got {got}")

A few deliberate choices in that small block:

  • The canary uses a unique timestamp each run, so a stale leftover value can never fool the check into a false “healthy.”
  • ex=30 gives the canary a 30-second TTL, so it cleans up after itself and never clutters the cache.
  • ssl=True is required because of encryption in transit, and ValkeyCluster (not the plain client) is used because the cache runs in cluster mode.
  • decode_responses=True returns plain strings instead of raw bytes, so got compares cleanly.

To make it a genuine monitoring probe rather than a demo, you would add two small things: a proper exit code (sys.exit(0) on pass, sys.exit(1) on fail) so cron or a monitor can act on it, and a connect timeout so it fails in a few seconds instead of hanging when the cache is down. The Python patterns behind this live in my Python Basics & CLI cheatsheet, and if you script AWS more broadly, the Python Boto3 cheatsheet is the companion piece.

Common pitfalls, and how to avoid them

  • Connecting from your laptop. ElastiCache is VPC-only. Run your client on an EC2 instance (or another resource) inside the same VPC.
  • The default security group. The create wizard may attach the cache to default. Confirm it matches your client’s group, or the connection times out with no useful error.
  • Forgetting TLS. If encryption in transit is Required, every client needs it: --tls for the CLI, ssl=True in Python. Without it you hang.
  • Cluster mode surprises. Use the configuration endpoint and a cluster-aware client. Use SCAN instead of KEYS on large datasets to avoid stalling the server.
  • Leaving it running. The node bills per hour whether you use it or not. Delete it when you are done.

Step 7: Clean up so you are not billed

The cheap demo stays cheap only if you tear it down. In ElastiCache, delete the valkey-demo cache (skip the final backup). Then delete the subnet group, terminate the valkey-demo-client EC2 instance, and remove the demo security groups. That returns your hourly charges to zero.

0

Wrapping up

Running Valkey on AWS ElastiCache is mostly about the network around it: a security group the client shares, an EC2 box inside the VPC, and TLS on the wire. Once those line up, Valkey behaves exactly like the Redis you already know. Test interactively with valkey-cli, and reserve scripts for the repeatable jobs, like the health check, where code genuinely beats typing. Build it small, watch the timeouts, and delete it when you are done.

1

References and Further Reading

Question

Have you moved any workloads from Redis to Valkey yet, and what pushed the decision?

Similar Articles

More from cloud

Knowledge Quiz

Test your general knowledge with this quick quiz!

A set of multiple-choice questions to test your knowledge.

Take as much time as you need.

Your score will be shown at the end.