The aws:elasticache/serverlessCache:ServerlessCache resource, part of the Pulumi AWS provider, provisions ElastiCache Serverless caches that automatically scale capacity based on workload without managing nodes. This guide focuses on three capabilities: engine selection (Memcached, Redis, Valkey), usage limits for storage and compute, and snapshot configuration for Redis and Valkey.
Serverless caches run in VPC subnets with security groups and optionally use KMS keys for encryption. The examples are intentionally small. Combine them with your own VPC infrastructure and access controls.
Deploy a Memcached serverless cache with usage limits
Teams building session stores or simple caching layers often start with Memcached for its straightforward key-value semantics and low operational overhead.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.elasticache.ServerlessCache("example", {
engine: "memcached",
name: "example",
cacheUsageLimits: {
dataStorage: {
maximum: 10,
unit: "GB",
},
ecpuPerSeconds: [{
maximum: 5000,
}],
},
description: "Test Server",
kmsKeyId: test.arn,
majorEngineVersion: "1.6",
securityGroupIds: [testAwsSecurityGroup.id],
subnetIds: testAwsSubnet.map(__item => __item.id),
});
import pulumi
import pulumi_aws as aws
example = aws.elasticache.ServerlessCache("example",
engine="memcached",
name="example",
cache_usage_limits={
"data_storage": {
"maximum": 10,
"unit": "GB",
},
"ecpu_per_seconds": [{
"maximum": 5000,
}],
},
description="Test Server",
kms_key_id=test["arn"],
major_engine_version="1.6",
security_group_ids=[test_aws_security_group["id"]],
subnet_ids=[__item["id"] for __item in test_aws_subnet])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/elasticache"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
var splat0 []interface{}
for _, val0 := range testAwsSubnet {
splat0 = append(splat0, val0.Id)
}
_, err := elasticache.NewServerlessCache(ctx, "example", &elasticache.ServerlessCacheArgs{
Engine: pulumi.String("memcached"),
Name: pulumi.String("example"),
CacheUsageLimits: &elasticache.ServerlessCacheCacheUsageLimitsArgs{
DataStorage: &elasticache.ServerlessCacheCacheUsageLimitsDataStorageArgs{
Maximum: pulumi.Int(10),
Unit: pulumi.String("GB"),
},
EcpuPerSeconds: elasticache.ServerlessCacheCacheUsageLimitsEcpuPerSecondArray{
&elasticache.ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs{
Maximum: pulumi.Int(5000),
},
},
},
Description: pulumi.String("Test Server"),
KmsKeyId: pulumi.Any(test.Arn),
MajorEngineVersion: pulumi.String("1.6"),
SecurityGroupIds: pulumi.StringArray{
testAwsSecurityGroup.Id,
},
SubnetIds: toPulumiArray(splat0),
})
if err != nil {
return err
}
return nil
})
}
func toPulumiArray(arr []) pulumi.Array {
var pulumiArr pulumi.Array
for _, v := range arr {
pulumiArr = append(pulumiArr, pulumi.(v))
}
return pulumiArr
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.ElastiCache.ServerlessCache("example", new()
{
Engine = "memcached",
Name = "example",
CacheUsageLimits = new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsArgs
{
DataStorage = new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsDataStorageArgs
{
Maximum = 10,
Unit = "GB",
},
EcpuPerSeconds = new[]
{
new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs
{
Maximum = 5000,
},
},
},
Description = "Test Server",
KmsKeyId = test.Arn,
MajorEngineVersion = "1.6",
SecurityGroupIds = new[]
{
testAwsSecurityGroup.Id,
},
SubnetIds = testAwsSubnet.Select(__item => __item.Id).ToList(),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.elasticache.ServerlessCache;
import com.pulumi.aws.elasticache.ServerlessCacheArgs;
import com.pulumi.aws.elasticache.inputs.ServerlessCacheCacheUsageLimitsArgs;
import com.pulumi.aws.elasticache.inputs.ServerlessCacheCacheUsageLimitsDataStorageArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new ServerlessCache("example", ServerlessCacheArgs.builder()
.engine("memcached")
.name("example")
.cacheUsageLimits(ServerlessCacheCacheUsageLimitsArgs.builder()
.dataStorage(ServerlessCacheCacheUsageLimitsDataStorageArgs.builder()
.maximum(10)
.unit("GB")
.build())
.ecpuPerSeconds(ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs.builder()
.maximum(5000)
.build())
.build())
.description("Test Server")
.kmsKeyId(test.arn())
.majorEngineVersion("1.6")
.securityGroupIds(testAwsSecurityGroup.id())
.subnetIds(testAwsSubnet.stream().map(element -> element.id()).collect(toList()))
.build());
}
}
The engine property selects the cache type; Memcached provides simple key-value storage without persistence. The cacheUsageLimits block sets maximum storage (dataStorage) and compute capacity (ecpuPerSeconds), which ElastiCache uses to scale automatically. The majorEngineVersion specifies the Memcached version to run.
Deploy Redis with automated snapshots
Applications requiring persistence and point-in-time recovery use Redis with daily snapshots to protect against data loss.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.elasticache.ServerlessCache("example", {
engine: "redis",
name: "example",
cacheUsageLimits: {
dataStorage: {
maximum: 10,
unit: "GB",
},
ecpuPerSeconds: [{
maximum: 5000,
}],
},
dailySnapshotTime: "09:00",
description: "Test Server",
kmsKeyId: test.arn,
majorEngineVersion: "7",
snapshotRetentionLimit: 1,
securityGroupIds: [testAwsSecurityGroup.id],
subnetIds: testAwsSubnet.map(__item => __item.id),
});
import pulumi
import pulumi_aws as aws
example = aws.elasticache.ServerlessCache("example",
engine="redis",
name="example",
cache_usage_limits={
"data_storage": {
"maximum": 10,
"unit": "GB",
},
"ecpu_per_seconds": [{
"maximum": 5000,
}],
},
daily_snapshot_time="09:00",
description="Test Server",
kms_key_id=test["arn"],
major_engine_version="7",
snapshot_retention_limit=1,
security_group_ids=[test_aws_security_group["id"]],
subnet_ids=[__item["id"] for __item in test_aws_subnet])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/elasticache"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
var splat0 []interface{}
for _, val0 := range testAwsSubnet {
splat0 = append(splat0, val0.Id)
}
_, err := elasticache.NewServerlessCache(ctx, "example", &elasticache.ServerlessCacheArgs{
Engine: pulumi.String("redis"),
Name: pulumi.String("example"),
CacheUsageLimits: &elasticache.ServerlessCacheCacheUsageLimitsArgs{
DataStorage: &elasticache.ServerlessCacheCacheUsageLimitsDataStorageArgs{
Maximum: pulumi.Int(10),
Unit: pulumi.String("GB"),
},
EcpuPerSeconds: elasticache.ServerlessCacheCacheUsageLimitsEcpuPerSecondArray{
&elasticache.ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs{
Maximum: pulumi.Int(5000),
},
},
},
DailySnapshotTime: pulumi.String("09:00"),
Description: pulumi.String("Test Server"),
KmsKeyId: pulumi.Any(test.Arn),
MajorEngineVersion: pulumi.String("7"),
SnapshotRetentionLimit: pulumi.Int(1),
SecurityGroupIds: pulumi.StringArray{
testAwsSecurityGroup.Id,
},
SubnetIds: toPulumiArray(splat0),
})
if err != nil {
return err
}
return nil
})
}
func toPulumiArray(arr []) pulumi.Array {
var pulumiArr pulumi.Array
for _, v := range arr {
pulumiArr = append(pulumiArr, pulumi.(v))
}
return pulumiArr
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.ElastiCache.ServerlessCache("example", new()
{
Engine = "redis",
Name = "example",
CacheUsageLimits = new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsArgs
{
DataStorage = new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsDataStorageArgs
{
Maximum = 10,
Unit = "GB",
},
EcpuPerSeconds = new[]
{
new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs
{
Maximum = 5000,
},
},
},
DailySnapshotTime = "09:00",
Description = "Test Server",
KmsKeyId = test.Arn,
MajorEngineVersion = "7",
SnapshotRetentionLimit = 1,
SecurityGroupIds = new[]
{
testAwsSecurityGroup.Id,
},
SubnetIds = testAwsSubnet.Select(__item => __item.Id).ToList(),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.elasticache.ServerlessCache;
import com.pulumi.aws.elasticache.ServerlessCacheArgs;
import com.pulumi.aws.elasticache.inputs.ServerlessCacheCacheUsageLimitsArgs;
import com.pulumi.aws.elasticache.inputs.ServerlessCacheCacheUsageLimitsDataStorageArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new ServerlessCache("example", ServerlessCacheArgs.builder()
.engine("redis")
.name("example")
.cacheUsageLimits(ServerlessCacheCacheUsageLimitsArgs.builder()
.dataStorage(ServerlessCacheCacheUsageLimitsDataStorageArgs.builder()
.maximum(10)
.unit("GB")
.build())
.ecpuPerSeconds(ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs.builder()
.maximum(5000)
.build())
.build())
.dailySnapshotTime("09:00")
.description("Test Server")
.kmsKeyId(test.arn())
.majorEngineVersion("7")
.snapshotRetentionLimit(1)
.securityGroupIds(testAwsSecurityGroup.id())
.subnetIds(testAwsSubnet.stream().map(element -> element.id()).collect(toList()))
.build());
}
}
Redis adds persistence features not available in Memcached. The dailySnapshotTime property schedules when ElastiCache creates backups, and snapshotRetentionLimit controls how many snapshots to keep before deleting the oldest. These properties are only valid for Redis and Valkey engines.
Deploy Valkey with snapshot retention
Valkey provides Redis-compatible caching with the same persistence and snapshot capabilities for teams seeking an open-source alternative.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.elasticache.ServerlessCache("example", {
engine: "valkey",
name: "example",
cacheUsageLimits: {
dataStorage: {
maximum: 10,
unit: "GB",
},
ecpuPerSeconds: [{
maximum: 5000,
}],
},
dailySnapshotTime: "09:00",
description: "Test Server",
kmsKeyId: test.arn,
majorEngineVersion: "7",
snapshotRetentionLimit: 1,
securityGroupIds: [testAwsSecurityGroup.id],
subnetIds: testAwsSubnet.map(__item => __item.id),
});
import pulumi
import pulumi_aws as aws
example = aws.elasticache.ServerlessCache("example",
engine="valkey",
name="example",
cache_usage_limits={
"data_storage": {
"maximum": 10,
"unit": "GB",
},
"ecpu_per_seconds": [{
"maximum": 5000,
}],
},
daily_snapshot_time="09:00",
description="Test Server",
kms_key_id=test["arn"],
major_engine_version="7",
snapshot_retention_limit=1,
security_group_ids=[test_aws_security_group["id"]],
subnet_ids=[__item["id"] for __item in test_aws_subnet])
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/elasticache"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
var splat0 []interface{}
for _, val0 := range testAwsSubnet {
splat0 = append(splat0, val0.Id)
}
_, err := elasticache.NewServerlessCache(ctx, "example", &elasticache.ServerlessCacheArgs{
Engine: pulumi.String("valkey"),
Name: pulumi.String("example"),
CacheUsageLimits: &elasticache.ServerlessCacheCacheUsageLimitsArgs{
DataStorage: &elasticache.ServerlessCacheCacheUsageLimitsDataStorageArgs{
Maximum: pulumi.Int(10),
Unit: pulumi.String("GB"),
},
EcpuPerSeconds: elasticache.ServerlessCacheCacheUsageLimitsEcpuPerSecondArray{
&elasticache.ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs{
Maximum: pulumi.Int(5000),
},
},
},
DailySnapshotTime: pulumi.String("09:00"),
Description: pulumi.String("Test Server"),
KmsKeyId: pulumi.Any(test.Arn),
MajorEngineVersion: pulumi.String("7"),
SnapshotRetentionLimit: pulumi.Int(1),
SecurityGroupIds: pulumi.StringArray{
testAwsSecurityGroup.Id,
},
SubnetIds: toPulumiArray(splat0),
})
if err != nil {
return err
}
return nil
})
}
func toPulumiArray(arr []) pulumi.Array {
var pulumiArr pulumi.Array
for _, v := range arr {
pulumiArr = append(pulumiArr, pulumi.(v))
}
return pulumiArr
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
return await Deployment.RunAsync(() =>
{
var example = new Aws.ElastiCache.ServerlessCache("example", new()
{
Engine = "valkey",
Name = "example",
CacheUsageLimits = new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsArgs
{
DataStorage = new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsDataStorageArgs
{
Maximum = 10,
Unit = "GB",
},
EcpuPerSeconds = new[]
{
new Aws.ElastiCache.Inputs.ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs
{
Maximum = 5000,
},
},
},
DailySnapshotTime = "09:00",
Description = "Test Server",
KmsKeyId = test.Arn,
MajorEngineVersion = "7",
SnapshotRetentionLimit = 1,
SecurityGroupIds = new[]
{
testAwsSecurityGroup.Id,
},
SubnetIds = testAwsSubnet.Select(__item => __item.Id).ToList(),
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.elasticache.ServerlessCache;
import com.pulumi.aws.elasticache.ServerlessCacheArgs;
import com.pulumi.aws.elasticache.inputs.ServerlessCacheCacheUsageLimitsArgs;
import com.pulumi.aws.elasticache.inputs.ServerlessCacheCacheUsageLimitsDataStorageArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new ServerlessCache("example", ServerlessCacheArgs.builder()
.engine("valkey")
.name("example")
.cacheUsageLimits(ServerlessCacheCacheUsageLimitsArgs.builder()
.dataStorage(ServerlessCacheCacheUsageLimitsDataStorageArgs.builder()
.maximum(10)
.unit("GB")
.build())
.ecpuPerSeconds(ServerlessCacheCacheUsageLimitsEcpuPerSecondArgs.builder()
.maximum(5000)
.build())
.build())
.dailySnapshotTime("09:00")
.description("Test Server")
.kmsKeyId(test.arn())
.majorEngineVersion("7")
.snapshotRetentionLimit(1)
.securityGroupIds(testAwsSecurityGroup.id())
.subnetIds(testAwsSubnet.stream().map(element -> element.id()).collect(toList()))
.build());
}
}
Valkey uses identical snapshot configuration to Redis. The engine property switches to “valkey” while dailySnapshotTime and snapshotRetentionLimit work the same way. Valkey offers Redis compatibility with an open-source license.
Beyond these examples
These snippets focus on specific serverless cache features: engine selection (Memcached, Redis, Valkey), usage limits and capacity planning, and snapshot configuration and retention. They’re intentionally minimal rather than full caching solutions.
The examples reference pre-existing infrastructure such as VPC subnets and security groups, and KMS keys for encryption. They focus on configuring the cache rather than provisioning the surrounding network.
To keep things focused, common cache patterns are omitted, including:
- Snapshot restoration (snapshotArnsToRestores)
- User group authentication (userGroupId)
- Custom endpoint configuration
- Tag-based organization and cost tracking
These omissions are intentional: the goal is to illustrate how each cache feature is wired, not provide drop-in caching modules. See the ElastiCache ServerlessCache resource reference for all available configuration options.
Let's create AWS ElastiCache Serverless Caches
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Engine Selection & Features
memcached, redis, and valkey.Snapshot features vary by engine:
dailySnapshotTimeis supported forredisandvalkeyonlysnapshotRetentionLimitis available for Redis onlysnapshotArnsToRestoresis available for Redis only
userGroupId) are available for Redis and Valkey only. The default is NULL.Cache Configuration
Set cacheUsageLimits with two components:
dataStoragewithmaximumandunit(e.g., 10 GB)ecpuPerSecondswithmaximum(e.g., 5000)
dailySnapshotTime defaults to 0 for Redis and Valkey engines.Networking & Security
subnetIds must belong to the same VPC.securityGroupIds for VPC endpoint access. If not specified, the VPC’s default security group will be used.kmsKeyId (ARN of a customer managed key) for encrypting data at rest. If not provided, a default service key is used.subnetIds must belong to the same VPC.