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.
Overview
Section titled “Overview”An instance is configured in three places, and each setting comes from the first one that sets it:
- The tenant’s override in the Tenant Model, under
modular_features.modules.<module-name>.values_override.infrastructure.elasticache.<name>. - Your default in the module manifest, under
spec.infrastructure.elasticache.<name>.defaultConfig, whichcatalog createcopies into the Module Catalog entry. - 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”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:
apiVersion: runway/v3kind: RunwayManifestmetadata: name: example-service-dedicatedspec: infrastructure: elasticache: cache: defaultConfig: enabled: false instanceType: xsmallA 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.
Step 3: Override per tenant, if needed
Section titled “Step 3: Override per tenant, if needed”A tenant that needs the cache turns it on, without repeating the other settings:
{ "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.
Field reference
Section titled “Field reference”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.
Node types
Section titled “Node types”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 |
Enabling and disabling
Section titled “Enabling and disabling”Every instance has an enabled field.
Unset means enabled.
- Off by default: set
enabled: falsein thedefaultConfig, as in the example above. The defaults are still checked, so that they are sane when a tenant turns the instance on withenabled: true. AREQUIREDRedis dependency can’t be off by default. - Off for one tenant: the tenant sets
enabled: false. Runway doesn’t provision the instance, deploys noSecretand no Helm values for it, and doesn’t check its other settings. For aREQUIREDdependency, this is an error.
What gets created
Section titled “What gets created”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-networkingsecurity 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,usernamerunway/<module-name>/redis/<name>/passwordpasswordaddrsis<primary endpoint>:<port>.
deploy then:
- writes the Kubernetes
Secretredis-<name>in the module’s namespace, with the keysaddrs,username, andpassword, and theSecretredis-<name>-tlswith the CA bundle that the ElastiCache server certificates chain to, asca.crt; - points
infrastructure.redis.secretRefin your Helm values at the first, andinfrastructure.redis.tlsSecretNameat the second.
Rotating the password
Section titled “Rotating the password”- Increase
password_versionin the Tenant Model, and provision the module. Runway generates a new password and applies it to therunwayuser and to AWS Secrets Manager in the same apply. - Deploy the module, which updates the Kubernetes
Secret. - 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.