Skip to content

ElastiCache for Valkey

Runway can provision a Redis-compatible Amazon ElastiCache for Valkey instance in the AWS account of every Dedicated tenant that enables your module, and wire it into your Helm chart through the Fairway infrastructure.redis contract. Runway owns the instance and its credentials: runwayctl dedicated provision creates the replication group and the runway user with a generated password, and runwayctl dedicated deploy gives your workload the connection details and the CA bundle for TLS. You don’t create or manage the secrets yourself.

This page assumes your module is set up for Dedicated. If it isn’t, start with Getting Started.

An instance is configured in three places, and each setting comes from the first one that sets it:

  1. The tenant’s override in the Tenant Model, under modular_features.modules.<module-name>.values_override.infrastructure.elasticache.<name>.
  2. Your default in the module manifest, under spec.infrastructure.elasticache.<name>.defaultConfig, which catalog create copies into the Module Catalog entry.
  3. The built-in default in the field reference.

<name> is the instance’s logical name, a name of your choice that the module manifest and the Tenant Model share. Entries are merged by logical name and then field by field, so a tenant only sets what differs. Whether your module needs Redis at all is its redis presence in the Fairway manifest.

Step 1: Declare the dependency in your Fairway manifest

Section titled “Step 1: Declare the dependency in your Fairway manifest”
.runway/fairway.yaml
spec:
infrastructure:
redis:
presence: OPTIONAL
Presence Module manifest Tenant Model, after the merge
REQUIRED Needs at least one enabled default. Needs exactly one enabled instance.
OPTIONAL Any defaults, enabled or not, or none. At most one enabled instance.
UNUSED Must have no defaults, not even disabled ones. Must have no enabled instance.

catalog create checks the module manifest against the presence when you release the module. provision and deploy check the merged result on every tenant.

Don’t set spec.values.infrastructure.redis.secretRef or tlsSecretName yourself. Runway sets them, and overwrites anything you put there with a warning. Other redis settings, such as clientName or db, are yours to set and are kept.

Step 2: Set the defaults in your module manifest

Section titled “Step 2: Set the defaults in your module manifest”

This module uses Redis on some tenants only, so the default is off:

.runway/module.yaml
apiVersion: runway/v3
kind: RunwayManifest
metadata:
name: example-service-dedicated
spec:
infrastructure:
elasticache:
cache:
defaultConfig:
enabled: false
instanceType: xsmall

A defaultConfig must be valid on its own, without any override, including when it is disabled. defaultConfig: {} is valid and gives the built-in defaults. Field names can be in camelCase or snake_case.

A tenant that needs the cache turns it on, without repeating the other settings:

Tenant Model
{
"modular_features": {
"modules": {
"example-service-dedicated": {
"enabled": true,
"version": "v1.26.0",
"values_override": {
"infrastructure": {
"elasticache": {
"cache": { "enabled": true }
}
}
}
}
}
}
}

For this tenant, the instance is xsmall, from the module manifest, and runs Valkey 8.1 with two cache clusters in different availability zones, from the built-in defaults. Tenants without the override get no instance.

The override is partial: it only has to parse, with the right types and no unknown fields. The merged instance is validated as a complete configuration, where an unset field stands for its built-in default. For example, num_cache_clusters: 1 fails unless multi_az is false in the override or the default. A tenant can also add an instance that has no default, which must then be complete on its own.

InfrastructureConfigElastiCache in runwayctl’s elasticache.proto. Unknown fields are rejected.

Field Type Default Description
enabled boolean true Provisions the instance. See Enabling and disabling.
instance_type string 2xsmall Node type, as a load category.
engine_version string "8.1" Valkey version as major.minor, 7.2 or later. ElastiCache applies patch upgrades automatically.
multi_az boolean true Places the cache clusters in different availability zones with automatic failover.
num_cache_clusters integer 2 if multi_az is true, 1 otherwise Number of cache clusters (one primary plus replicas), from 1 to 6. At least 2 unless multi_az is false.
password_version integer 1 Version of the password of the runway user. At least 1. See Rotating the password.

Logical names are lowercase letters, digits, and single hyphens, starting with a letter and not ending with a hyphen, at most 45 characters.

instance_type takes a load category, which maps to an ElastiCache Graviton node type:

instance_type ElastiCache node type
2xsmall cache.t4g.small
xsmall cache.t4g.medium
small cache.m7g.large
medium cache.m7g.xlarge
large cache.m7g.2xlarge
xlarge cache.m7g.4xlarge
2xlarge cache.m7g.8xlarge

Every instance has an enabled field. Unset means enabled.

  • Off by default: set enabled: false in the defaultConfig, as in the example above. The defaults are still checked, so that they are sane when a tenant turns the instance on with enabled: true. A REQUIRED Redis dependency can’t be off by default.
  • Off for one tenant: the tenant sets enabled: false. Runway doesn’t provision the instance, deploys no Secret and no Helm values for it, and doesn’t check its other settings. For a REQUIRED dependency, this is an error.

provision creates, in the tenant’s AWS account and region:

  • The replication group <tenant-id>-<module-name>-<name>-<digest>. The digest is the first 8 hex characters of the SHA-256 of <account>/<tenant-id>/<module-name>/<name>, so two tenants or modules never collide. ElastiCache limits the identifier to 40 characters, so <module-name>-<name> is shortened, keeping the tenant prefix and the digest; the longest tenant IDs leave no room for it. The instance uses encryption in transit and at rest, is placed in the tenant’s managed-services subnets, and accepts connections only from the tenant’s <tenant-id>-internal-networking security group. It is encrypted with the tenant’s default customer-managed key from the Tenant Model, or with a key per instance if it has none.

  • The RBAC user runway, with a generated password.

  • Two secrets in AWS Secrets Manager, encrypted with alias/<tenant-id>-tenant-secrets-kms-key:

    Secret Keys
    runway/<module-name>/redis/<name> addrs, username
    runway/<module-name>/redis/<name>/password password

    addrs is <primary endpoint>:<port>.

deploy then:

  • writes the Kubernetes Secret redis-<name> in the module’s namespace, with the keys addrs, username, and password, and the Secret redis-<name>-tls with the CA bundle that the ElastiCache server certificates chain to, as ca.crt;
  • points infrastructure.redis.secretRef in your Helm values at the first, and infrastructure.redis.tlsSecretName at the second.
  1. Increase password_version in the Tenant Model, and provision the module. Runway generates a new password and applies it to the runway user and to AWS Secrets Manager in the same apply.
  2. Deploy the module, which updates the Kubernetes Secret.
  3. Restart the module’s workloads, so that they read the new password.

ElastiCache applies a single password, so new connections fail between the provision and the restart. Provision, deploy, and restart back to back. Only ever increase the version.