> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Trade-offs in AWS ElastiCache

> Choose a Valkey or Redis adapter around eviction, command behavior, recovery and who operates the cache.

Start by deciding whether losing the contents causes a cache miss or loses application state. A product catalog cache can recover from its database. A stream with unique events, a coordination counter or a session that exists nowhere else needs a different recovery contract.

A service adapter includes the origin and target: AWS ElastiCache to Memorystore and AWS ElastiCache to operated Valkey are different adapters. Memorystore or Valkey alone names the backend. The comparisons below keep the ElastiCache origin while changing the target and operating model.

This article covers ElastiCache's Valkey and Redis workloads, not Memcached. Your application sends RESP commands directly to the selected engine. The ElastiCache management interface used to discover an endpoint is a separate path; changing its AWS SDK endpoint does not redirect a Redis client. Configure that client's host, port, TLS and authentication for the destination.

## General trade-offs

Compare the command and recovery contract before selecting a node size. This page focuses on provisioned Valkey and Redis workloads. Confirm the origin shape in the [provisioned service catalog](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-provisioned) or [serverless-origin profile](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-serverless). A serverless origin does not imply serverless target capacity or billing.

Use the environment sections below to identify the target cache and its operating model. A RESP-compatible product available in a cloud is not automatically another adapter for that environment.

### Commands, topology and recovery

| Question                                                      | Why it changes the decision                                                                      |
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| Which commands and options does the application actually use? | A successful connection and GET do not establish Lua, functions, streams or module compatibility |
| Are all keys disposable?                                      | Eviction and restoration become correctness decisions when the cache contains the only copy      |
| Which keys must change atomically?                            | Cluster slots and multi-key restrictions can require a different topology or key design          |
| What happens after an acknowledged write and failover?        | Replication, persistence and recovery are separate from normal write success                     |
| How does capacity grow?                                       | A larger managed SKU, more shards and a larger multicore node have different disruption and cost |
| Who restores service at night?                                | Engine access is useful only when someone owns storage, credentials, failover and backups        |

Keep engine versions and command exceptions in the catalog review. In particular, classic Memorystore for Redis is a different topology from Memorystore's clustered products. Azure's module requirements can constrain both clustering and eviction policy.

### Operating ownership

| Work                                        | Managed engine                                          | Customer-operated engine                           |
| ------------------------------------------- | ------------------------------------------------------- | -------------------------------------------------- |
| Engine maintenance and node recovery        | Provider within its service contract                    | Named platform operator                            |
| Memory, eviction and workload limits        | Application/platform team                               | Application/platform team                          |
| Backup requirement and restore acceptance   | Your team, using provider mechanisms                    | Your team, including backup storage and scheduling |
| TLS, access and renewal                     | Shared provider configuration and client responsibility | Your team across engine and clients                |
| Cache-miss protection and state correctness | Application team                                        | Application team                                   |

Keep a decision record with the engine version, topology, command fixture, loss/miss budget, failure observations and the person who can perform recovery in the customer's environment. Compare cost only after these requirements pass.

## Google Cloud

### Memorystore for Redis

The documented backend is the classic Memorystore for Redis instance. Google operates the engine and failover mechanism; your team owns capacity, eviction policy, access and recovery acceptance. The strength of this option is managed operation for a workload that fits its single-primary shape and supported Redis command set.

It is not the same engine or topology as a sharded Valkey replication group. Valkey-specific commands, required modules and multi-shard capacity can disqualify this mapping even when ordinary GET and SET succeed. Memorystore for Redis Cluster and Memorystore for Valkey are distinct products, not settings that turn this adapter into a different one. Check the [Memorystore mapping](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-provisioned#on-google-cloud) against the exact commands and topology you require.

### Workload example: disposable product summaries

A storefront caches rendered product summaries for five minutes while PostgreSQL remains authoritative. It uses GET, SET with expiry and deletion after updates. Memorystore fits this shape when the working set and command set fit its instance model and the team wants provider-operated cache infrastructure. A workload requiring an unsupported Valkey command or more write capacity than the single-primary design permits needs a different documented deployment design; increasing read replicas does not resolve either requirement.

Budget for memory headroom and the database's extra work during warm-up. Cut over a small application cohort to an empty test cache and bound database concurrency. Check invalidation while both endpoints are in use. Keeping the old endpoint provides a reversal path only if its stale values expire or are invalidated before clients return.

### Run a bounded cache-pressure probe

This first probe tests the disposable-cache example. It does not certify stream durability or distributed locking. It uses a tiny authoritative fixture in the script so that missing cache entries can be checked unambiguously; repeat the workload through your real application's database-backed path to measure the production miss cost.

<Steps>
  <Step title="Prepare an isolated cache">
    Use a dedicated single-endpoint test cache with no customer data. Configure a supported evicting policy through its deployment/control plane and record that policy. Permit INFO for the test identity, use TLS and obtain its CA certificate if it is not publicly trusted. Do not turn off certificate verification.

    This is a native RESP test, so it does not require a local `tensor9 adapt svc run` process. A management adapter cannot provision or resize a cache simply because you start it. Provision the target through your deployment workflow and use its native endpoint.
  </Step>

  <Step title="Run the fixture">
    Install the Python client with `python3 -m pip install redis`. Save this as `cache-pressure-check.py`, replace the example hostname and port with the test endpoint, and run `python3 cache-pressure-check.py`. Supply the test username and password when prompted. For a target using token authentication, use its documented token and renewal mechanism instead.

    The run refuses an existing test namespace, writes at most 2 GiB of disposable values, and stops after observing an eviction. The payload cap is a safety bound, not a recommended cache size. Set a lower bound in the code if your test budget requires it.

    ```python theme={null}
    import getpass
    import time
    import redis

    client = redis.Redis(
        host="cache-test.example.com", port=6379,
        username=input("Test cache username (blank if unused): ") or None,
        password=getpass.getpass("Test cache password: "),
        ssl=True, ssl_cert_reqs="required",
        socket_connect_timeout=5, socket_timeout=5,
        decode_responses=True,
    )
    client.ping()
    prefix = "tradeoff-cache-check:"
    if next(client.scan_iter(match=prefix + "*"), None) is not None:
        raise RuntimeError("Test keys already exist; inspect them before retrying")
    source = {"product-a": "price=25", "product-b": "price=70"}
    first_evictions = int(client.info("stats")["evicted_keys"])
    inserted = 0
    misses = 0
    observed_eviction = False
    started = time.monotonic()
    try:
        for key, value in source.items():
            client.set(prefix + key, value, ex=300)
        for i in range(32768):
            client.set(prefix + "filler:" + str(i), "x" * 65536, ex=300)
            inserted = i + 1
            for key, authoritative in source.items():
                value = client.get(prefix + key)
                if value is None:
                    misses += 1
                    value = authoritative
                    client.set(prefix + key, value, ex=300)
                if value != authoritative:
                    raise RuntimeError("Incorrect application value for " + key)
            if i % 64 == 0:
                observed_eviction = (
                    int(client.info("stats")["evicted_keys"]) > first_evictions
                )
                if observed_eviction:
                    break
        print({"keys_written": inserted, "fixture_misses": misses,
               "elapsed_seconds": round(time.monotonic() - started, 2),
               "eviction_observed": observed_eviction})
        if not observed_eviction:
            raise RuntimeError("INCONCLUSIVE: payload cap reached without eviction")
    finally:
        # Only this run's known keys; no FLUSHDB or wildcard deletion.
        for i in range(inserted):
            client.delete(prefix + "filler:" + str(i))
        for key in source:
            client.delete(prefix + key)
        client.close()
    ```

    An interrupted cleanup leaves only namespaced keys with a five-minute TTL. Do not rerun while a previous process still writes this namespace. See the [Redis client connection reference](https://redis.io/docs/latest/develop/clients/redis-py/connect/) for your target's TLS options.
  </Step>

  <Step title="Interpret the observation">
    Expected: the native eviction counter increases and every successful fixture read returns its authoritative value. Zero misses for the two hot keys can be legitimate because other keys were evicted. No observed eviction is inconclusive, not a pass; use a smaller dedicated cache or an explicitly approved larger test budget.

    Write rejection points to policy or capacity, a timeout needs investigation, and an incorrect returned value fails correctness. Inspect the configured policy and native metrics before increasing capacity. The [eviction reference](https://redis.io/docs/latest/develop/reference/eviction/) explains the counter and policy distinction.
  </Step>

  <Step title="Qualify the application and clean up">
    Repeat through the real read-through path with representative key skew, values and concurrency. Set the maximum database request rate and p99 response budget before the run. Test cold start and a controlled failover separately. Reject a capacity/warm-up plan that exceeds either budget even if the cache itself stays responsive.

    Stop generators, verify the test keys are gone, and retire dedicated infrastructure through its deployment workflow. Preserve only nonsecret results and configuration. Explain can inspect management decisions; it does not trace GET/SET traffic sent directly to the engine.
  </Step>
</Steps>

## Microsoft Azure

### Azure Managed Redis

Azure Managed Redis runs a Redis Enterprise engine under Microsoft's operation. Its supported JSON and search modules can suit applications whose cache also serves document queries. The trade-offs include its engine-specific command set, capacity tiers, clustering policies and module constraints. A Valkey command is not supported merely because the client connects over RESP.

Use the [Azure mapping](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-provisioned#on-azure) to compare the required module versions, multi-key behavior and topology. Select the clustering policy before assuming a transaction can update keys in different slots. Cache settings belong to the control plane rather than runtime CONFIG commands.

### Workload example: JSON search

A customer-support product stores JSON documents and serves module-backed searches. Azure Managed Redis is a candidate when its modules and query behavior match the application's fixtures and managed engine operation fits the team's responsibilities. A mandatory module version or Valkey-only command absent from that mapping excludes it; a larger capacity tier does not repair that mismatch.

Search changes the memory calculation. The documented RediSearch configuration requires its supported clustering policy and no-eviction behavior. Size for documents, indexes, temporary work and growth. Test how write failures reach the application when the memory budget is exhausted, and exercise the capacity-change procedure before production depends on it.

For migration, copy source documents through the supported transfer path, rebuild indexes and compare query results before switching reads. A completed key copy does not establish that indexes are ready. Keep the source until both document updates and query answers are reconciled. Do not use the evicting-cache probe above as acceptance evidence for this no-eviction search workload.

## DigitalOcean

### Managed Valkey

DigitalOcean Managed Valkey provides a provider-operated Valkey engine. It can fit workloads that use the supported core command set and fit the mapped primary's capacity. The trade-offs include the mapped topology, service-defined persistence, access controls and recovery options. A cluster-mode ElastiCache workload cannot assume its keyspace is spread across equivalent target shards.

Compare the application's commands, required memory, write rate and recovery budget with the configured managed plan. DigitalOcean distinguishes standby availability from read-only replicas and does not offer its general managed-database backup/restore feature for Valkey. Do not budget for read scaling or recoverability on that assumption. Modules or exact engine features outside the managed command set are compatibility requirements, not sizing problems. See the [DigitalOcean service limits](https://docs.digitalocean.com/products/databases/valkey/details/limits/) and [managed-cache tuning guidance](/cloud-adapter/tuning/aws-elasticache#managed-alternatives-and-limits).

### Workload example: event processing with streams

A worker service uses Valkey streams for events that do not exist in another durable queue. Consumers maintain pending work and acknowledge completed entries. Keeping the RESP client avoids a protocol rewrite, but does not answer what survives a primary failure.

Test the exact stream commands and options, consumer recovery, acknowledged writes followed by connection loss, and restoration of pending work. Accept the managed deployment only when retained history and observed recovery meet the workload's tolerated loss and redelivery. The provider operates the engine; the application team still owns idempotent side effects and consumer recovery. If the available recovery contract does not fit, change the persistence design before production rather than tuning memory around it.

Account for retained events, standby capacity and memory consumed by pending work. Shortening retention is a data-retention decision: test it against the slowest permitted consumer and longest expected outage. Define any independent recoverable copy explicitly; provider-managed persistence is not an application backup policy.

Migration needs a fenced transfer of state and consumer positions. Rewarming a cache cannot recover unique stream entries. Specify which side accepts new events, when consumers stop, and how to reconcile events written after cutover if you return to the source.

## OCI

### OCI Cache

OCI Cache offers an Oracle-operated Redis or Valkey engine with sharded and non-sharded cluster choices. It can fit a workload requiring managed cache operation in OCI when the chosen engine, topology and commands match the application's contract. Compare shard count and per-shard capacity with the actual key distribution rather than treating total memory as sufficient evidence.

Persistence and backup controls differ from an operated Valkey server. Do not assume you can reproduce the source AOF policy with an engine setting, or that a backup exists on the schedule the application requires. Establish the permitted backup, export, restore and access procedures through the service's control plane. Check the [OCI Cache overview](https://docs.oracle.com/en-us/iaas/Content/ocicache/overview.htm) and [managed-cache tuning guidance](/cloud-adapter/tuning/aws-elasticache#managed-alternatives-and-limits).

For a disposable cache, qualify eviction, cold-start misses and the database's recovery load. For sessions or stream history that cannot be reconstructed, test acknowledged-write loss and recovery into a new isolated cluster. Require a restoration result with usable credentials and endpoints, not only a completed backup operation. Oracle owns the managed engine; the application and platform teams own the recovery requirement and its exercised procedure.

## Scaleway

### Managed Redis, Valkey or Dragonfly

Compare the managed and operated caches within the same required region and network:

| Backend                              | Strengths and workload fit                                                                            | Costs and constraints to accept                                                                                                                                           |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Scaleway Managed Database for Redis  | Provider-operated cache for a command-compatible, single-instance working set                         | The mapping's standalone topology, available engine version and exposed configuration determine fit; origin persistence and backup settings do not automatically transfer |
| Bitnami Valkey on the target cluster | Engine-version and persistence control when a platform team needs those controls and can operate them | Your team owns volumes, replication, failover, TLS, upgrades and restoration; match topology and eviction explicitly                                                      |
| Dragonfly on the target cluster      | Multicore engine execution for command-compatible workloads that fit a vertically sized node          | Its cache mode, command exceptions and single-node cluster presentation differ from Valkey Cluster; your team operates replication, snapshots and recovery                |

For disposable session lookups backed by a durable database, test expiry, eviction and miss load on each candidate. For a stream holding unique events, compare retained history and consumer recovery after failover before considering cost. Neither managed operation nor an acknowledged write establishes the tolerated data-loss contract.

The [managed Redis profile](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-provisioned#scaleway-managed-database-for-redis) and [Valkey profile](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-provisioned#bitnami-valkey) describe different control surfaces. Set the managed service's supported engine settings deliberately. On Valkey, establish the image version, persistence and primary/replica or Cluster topology through deployment configuration.

For Dragonfly, test the exact stream or cache fixture before comparing throughput. A successful cluster-aware connection does not establish Redis Cluster slot sharding. Use its supported cache mode rather than copying a Valkey eviction-policy string, and include operating work in the comparison. See [operated-cache tuning](/cloud-adapter/tuning/aws-elasticache#example-an-operated-valkey-or-dragonfly-deployment).

For a serverless ElastiCache origin, read its [separate Scaleway profile](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-serverless). Do not assume the provisioned-origin menu applies to it.

## Akamai

### Bitnami Valkey or Dragonfly

Both backends run on the target Kubernetes cluster. Valkey gives the team engine-version, persistence and topology controls; Dragonfly offers a multicore, vertically sized engine with its own command and cache-mode behavior. Evaluate Valkey for a workload requiring its exact commands or configured cluster topology, and Dragonfly for a command-compatible workload whose concurrency fits that single-node model. Measure both with the application's key distribution before drawing a throughput conclusion.

The platform team owns storage, replica placement, failover, security updates and recovery for both. Dragonfly's single-node cluster presentation does not spread keys across Redis Cluster shards; a larger node is a different capacity change from adding shards. Its command exceptions and eviction controls must fit the workload before memory or CPU tuning matters.

A disposable cache can accept rewarming if its backing database survives the miss rate. Unique stream history requires a persistence and restore procedure instead. Match the source version, set the eviction policy and verify cluster-slot behavior; the chart's defaults are not a translation of every ElastiCache setting. See the [Valkey mapping](/cloud-adapter/service-catalog/aws/databases-storage/elasticache-valkey-provisioned#bitnami-valkey).

## Private Kubernetes

### Bitnami Valkey or Dragonfly

Valkey and Dragonfly both run inside the customer's cluster. Valkey exposes its engine configuration and configurable primary/replica or Cluster topology; Dragonfly uses a vertically sized multicore engine and a different cache-mode model. Compare required commands, multi-key behavior, eviction and recoverability before comparing resource cost. Existing Kubernetes capacity does not supply backup storage, a tested recovery process or permission to administer either cache automatically.

For correctness-bearing state, test a primary failure, a lost volume and consumer restart separately. Record how much acknowledged state can be lost and how the application detects incomplete recovery. For a disposable cache, use the bounded pressure probe against an isolated native endpoint and then test the actual database-backed miss path. In both cases, reserve memory for replication and recovery work as well as live keys.

Set the policy through the chosen engine's supported configuration. Dragonfly's [cache-mode configuration](https://github.com/dragonflydb/dragonfly#novel-cache-design) is not the full Valkey policy menu. A mandatory script, function or module must pass its own fixture on the selected engine; broad RESP compatibility is insufficient.

## Next steps

Record the directed adapter, engine version, topology, command fixture, tolerated miss or loss budget, and recovery owner. Then configure and test those choices with [Tuning AWS ElastiCache](/cloud-adapter/tuning/aws-elasticache).
