Skip to content

sufyman/nextjs-dynamodb-cache

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

nextjs-dynamodb-cache

Drop-in Next.js CacheHandler that stores ISR cache and tag-based revalidation in DynamoDB.

Built for Next.js deployments on AWS Amplify, Lambda, App Runner, ECS, or anywhere your filesystem is ephemeral — so your ISR cache and revalidateTag() calls actually survive deploys and work across instances.

npm install nextjs-dynamodb-cache

Why

The default Next.js cache handler writes to disk. On Amplify/Lambda/Fargate that means:

  • ISR pages re-render from scratch after every deploy
  • revalidateTag() only invalidates the instance that received the call
  • Multiple instances serve inconsistent stale content

This package replaces the filesystem cache with DynamoDB. Cache entries are shared across all instances and survive deploys. Tag revalidation uses a GSI so it's a single query, not a full-table scan.

Quick start

1. Create the DynamoDB table

npx nextjs-dynamodb-cache-create-table --table my-app-cache --region eu-central-1

This is idempotent. It creates the table, the tag-index GSI, and enables TTL on expiresAt. PAY_PER_REQUEST billing by default.

Or programmatically:

import { createCacheTable } from "nextjs-dynamodb-cache/create-table";

await createCacheTable({ tableName: "my-app-cache", region: "eu-central-1" });

2. Register the handler

// next.config.js
module.exports = {
  cacheHandler: require.resolve("./cache-handler.mjs"),
  cacheMaxMemorySize: 0, // disable in-memory cache so DDB is authoritative
};
// cache-handler.mjs
import { DynamoDBCacheHandler } from "nextjs-dynamodb-cache";

export default DynamoDBCacheHandler.configure({
  tableName: "my-app-cache",
  region: "eu-central-1",
  // optional: defaultTtlSeconds, keyPrefix, log, credentials
});

That's it. revalidateTag() and revalidatePath() now work cluster-wide.

IAM

The Lambda/Amplify role needs:

{
  "Effect": "Allow",
  "Action": [
    "dynamodb:GetItem",
    "dynamodb:PutItem",
    "dynamodb:DeleteItem",
    "dynamodb:Query",
    "dynamodb:BatchWriteItem"
  ],
  "Resource": [
    "arn:aws:dynamodb:eu-central-1:*:table/my-app-cache",
    "arn:aws:dynamodb:eu-central-1:*:table/my-app-cache/index/*"
  ]
}

Options

Option Default Description
tableName env NEXT_CACHE_DYNAMODB_TABLE or nextjs-cache DynamoDB table name
region env NEXT_CACHE_AWS_REGION / AWS_REGION / eu-central-1 AWS region
credentials default chain Explicit AWS credentials
tagIndexName tag-index GSI name used for revalidateTag
defaultTtlSeconds 604800 (7 days) TTL when Next.js omits revalidate
keyPrefix "" Prefix for keys (multi-app table sharing)
log true Verbose logs on errors and revalidations

How it works

  • Schema: single table, partition key key. Each entry has value, expiresAt (TTL), and optional tags.
  • Tags: for each tag a sentinel row __tag__<tag>__<key> is written. revalidateTag(t) queries the tag-index GSI on tag = t, collects the original cache keys, and batch-deletes them.
  • TTL: DynamoDB native TTL on expiresAt cleans up stale entries automatically — no cron required.
  • Resilience: every operation is wrapped in try/catch; a DynamoDB outage degrades to "cache miss," never a 500.

Status

Battle-tested in production on Next.js 16 + Amplify hosting on the HonestDog marketplace. Compatible with Next.js 14, 15, and 16 cache-handler APIs.

License

MIT

About

Drop-in Next.js 14/15/16 CacheHandler that stores ISR cache and tag revalidation in DynamoDB. Survives deploys on AWS Amplify, Lambda, App Runner, and other ephemeral runtimes.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors