Guide · AWS DynamoDB

MCP Server DynamoDB DAX — in-memory caching, item cache vs query cache, consistency

DAX (DynamoDB Accelerator) adds a write-through, in-memory cache in front of DynamoDB — reads that hit the cache return in microseconds instead of single-digit milliseconds — but it is VPC-only and introduces eventual consistency for reads immediately following a write. For MCP servers, three constraints define whether DAX is the right choice: VPC requirement — DAX clusters have no public endpoint, so your MCP server Lambda or ECS task must run in the same VPC; consistency model — DAX serves item-cache reads from its in-memory store with a default TTL of 5 minutes; a write to DynamoDB via the DAX client also updates the item cache (write-through), but a write that bypasses DAX (e.g., from the AWS Console or another service using the raw DynamoDB client) leaves a stale item in the cache until the TTL expires; and no support for strongly consistent reads from the cache — ConsistentRead: true in the DAX client bypasses the cache and reads directly from DynamoDB, negating the caching benefit.

TL;DR

Deploy DAX in the same VPC subnets as your MCP server. Use the DAX client (API-compatible with the DynamoDB Document client) for reads. All writes go through DAX write-through to keep the item cache consistent. Do not use ConsistentRead: true for hot-path reads — it bypasses DAX. Avoid DAX for session data that is updated by multiple services outside your MCP server. Fall back to the raw DynamoDB client for transactional writes (TransactWriteItems) — DAX does not support transactions.

Item cache vs query cache

DAX maintains two separate caches with independent TTL controls:

Cache typeDefault TTLWhat it storesWhen it's useful for MCP
Item cache5 minutesIndividual item results from GetItem and BatchGetItem; keyed by primary keySession reads: GetItem by session ID for every MCP tool call. High read-to-write ratio for popular sessions. Hot item protection — DAX absorbs read traffic for a session that is being read thousands of times per second.
Query cache1 minute (default)Result sets from Query and Scan; keyed by the full query parameters including filter expressionsStatus dashboards, analytics queries that run repeatedly with the same parameters. A Query with different parameters (even ExclusiveStartKey for pagination) is treated as a different cache key. Rarely useful for MCP server session management where every query has a unique partition key.

For MCP session management, the item cache is the valuable one. A hot session (a user running many tool calls in a session) triggers the same GetItem pk=session#abc repeatedly; DAX returns it from memory after the first read.

Setting up the DAX client

The DAX client is API-compatible with the DynamoDB Document client — swap the constructor, keep all command objects the same:

// Without DAX (standard DynamoDB):
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

const ddbClient = new DynamoDBClient({ region: "us-east-1" });
const ddb = DynamoDBDocumentClient.from(ddbClient);

// With DAX (drop-in replacement):
// npm install amazon-dax-client
import AmazonDaxClient from "amazon-dax-client";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";

const daxClient = new AmazonDaxClient({
  endpoints: [process.env.DAX_CLUSTER_ENDPOINT!],
  // DAX endpoint format: dax://my-cluster.abc123.dax-clusters.us-east-1.amazonaws.com
  region: "us-east-1",
  requestTimeout: 5000,
  // Item cache TTL: 300 seconds (5 minutes) — default
  // Query cache TTL: 60 seconds (1 minute) — default
});

const ddb = DynamoDBDocumentClient.from(daxClient as any);

// All GetItem, Query, Put, Update, Delete commands work unchanged
// TransactWriteItems is NOT supported by DAX — use DynamoDB client directly for transactions

DAX clusters are VPC-internal. The DAX endpoint hostname resolves to private IP addresses within the cluster's subnet. Your Lambda or ECS task must be in the same VPC and have a security group rule allowing outbound TCP 8111 (DAX unencrypted) or 9111 (DAX encrypted with TLS).

// CDK: DAX cluster in private subnets
import * as dax from "aws-cdk-lib/aws-dax";
import * as ec2 from "aws-cdk-lib/aws-ec2";

const daxSg = new ec2.SecurityGroup(this, "DaxSg", {
  vpc,
  description: "DAX cluster — allow access from MCP server only",
});

// MCP server Lambda/ECS must have this security group to reach DAX
daxSg.addIngressRule(
  ec2.Peer.securityGroupId(mcpServerSg.securityGroupId),
  ec2.Port.tcp(9111), // 9111 for TLS-encrypted DAX
  "Allow MCP server to reach DAX"
);

const daxSubnetGroup = new dax.CfnSubnetGroup(this, "DaxSubnetGroup", {
  subnetGroupName: "mcp-dax-subnet-group",
  subnetIds: vpc.privateSubnets.map((s) => s.subnetId),
});

const daxCluster = new dax.CfnCluster(this, "McpDaxCluster", {
  clusterName: "mcp-dax",
  nodeType: "dax.r4.large",          // smallest production node; t2.small for dev/test
  replicationFactor: 2,               // 1 primary + 1 replica; use 3 for production HA
  iamRoleArn: daxRole.roleArn,
  subnetGroupName: daxSubnetGroup.ref,
  securityGroupIds: [daxSg.securityGroupId],
  sseSpecification: { sseEnabled: true },
  clusterEndpointEncryptionType: "TLS",
});

Write-through semantics and cache staleness

DAX uses write-through for PutItem, UpdateItem, and DeleteItem: the write goes to DynamoDB and the item cache is updated (or invalidated) atomically. This keeps the cache consistent for writes coming through the DAX client.

Staleness occurs when writes bypass DAX:

For MCP session state, the safest strategy: route all reads through DAX, route all writes through DAX (for simple writes), and accept that transactional writes will leave the cache stale for up to the item cache TTL. If you need post-transaction reads to be immediately consistent, issue a GetItem with ConsistentRead: true which bypasses DAX and reads fresh from DynamoDB.

When NOT to use DAX for MCP servers

Common failure modes

SymptomCauseFix
Connection timeout to DAX endpoint from LambdaLambda is not in the same VPC as the DAX cluster, or security group does not allow TCP 9111 outbound from Lambda to DAXAdd VPC config to Lambda pointing to the VPC and private subnets containing DAX; add outbound rule on Lambda SG for TCP 9111 to DAX SG
Stale session data returned after write from Console or CLIWrite bypassed DAX; item cache still holds old value for up to 5 minutesFor debugging, use ConsistentRead: true to bypass DAX; in production, route all writes through DAX client to maintain write-through coherency
TransactWriteItems throws UnsupportedOperationExceptionDAX does not support DynamoDB transactionsKeep a separate raw DynamoDBClient (not DAX) for transactional writes; use DAX only for non-transactional reads and writes
DAX cluster is a hot cost center without proportional benefitRead-to-write ratio is low; the cluster is over-provisioned; or most reads use ConsistentRead: true which bypasses DAXCheck TotalRequestCount vs CacheHits CloudWatch metrics; if hit rate is below 50%, DAX is not cost-effective; return to raw DynamoDB and add application-level caching (Redis/Memcached) for selective session reads