Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Distributed Rate Limiter (DynamoDB + Lambda + CDK)

Serverless distributed rate limiter using the token bucket algorithm on DynamoDB, Lambda, and API Gateway — deployed with AWS CDK. TypeScript, ESM, Node 22, with atomic conditional writes and optimistic locking for correctness under concurrency.

Topics: rate-limiter · token-bucket · dynamodb · aws-lambda · api-gateway · aws-cdk · serverless · typescript · optimistic-locking · distributed-systems · nodejs

A per-client token bucket rate limiter built on serverless AWS primitives: API Gateway (HTTP API) → Lambda → DynamoDB, deployed with AWS CDK v2.

It bursts up to capacity, settles to a steady rate, stays correct under concurrent requests across Lambda instances (optimistic locking), cleans up idle clients via DynamoDB TTL, and fails open so the limiter can never take down the API it protects.

Architecture

Client ──GET /check (x-api-key)──> API Gateway HTTP API
                                        │  Lambda proxy integration
                                        ▼
                                     Lambda (token-bucket logic)
                                        │  GetItem / PutItem / UpdateItem
                                        ▼
                                     DynamoDB  RateLimitTable

One DynamoDB item per client holds tokens, lastRefill, version, expiresAt.

Project layout

Path Purpose
bin/app.ts CDK app entry point
lib/rate-limiter-stack.ts Infrastructure: table, Lambda, HTTP API, IAM
src/config.ts Tunables (capacity, rate, TTL, retries) read from env
src/bucket.ts Pure token-bucket math — no AWS, fully unit-tested
src/store.ts DynamoDB read/write with optimistic locking + retry
src/handler.ts Lambda entry: identify client, format HTTP response
test/bucket.test.ts Unit tests for the pure logic (node:test)

Prerequisites

  • Node.js 22+ (node --version)
  • AWS credentials configured (aws configure or SSO)
  • CDK bootstrapped once per account/region: npx cdk bootstrap

Quick start

npm install

# run the unit tests (no AWS needed)
npm test

# preview the infrastructure changes
npx cdk diff

# deploy
npm run deploy

On success CDK prints the endpoint:

RateLimiterStack.ApiUrl = https://xxxxxxxx.execute-api.<region>.amazonaws.com/check

Try it

API="https://xxxxxxxx.execute-api.<region>.amazonaws.com/check"

# single request — allowed
curl -i -H "x-api-key: acme" "$API"

# drain the bucket — first 10 succeed (200), the rest are rejected (429)
for i in $(seq 1 15); do
  curl -s -o /dev/null -w "%{http_code} " -H "x-api-key: acme" "$API"
done; echo

# prove concurrency safety — exactly 10 get through
seq 1 50 | xargs -P 50 -I{} curl -s -o /dev/null -w "%{http_code}\n" \
  -H "x-api-key: stress" "$API" | sort | uniq -c

Responses carry X-RateLimit-Limit, X-RateLimit-Remaining, and (on 429) Retry-After.

Configuration

All tunables are environment variables with defaults (see src/config.ts):

Variable Default Meaning
BUCKET_CAPACITY 10 Max tokens (burst size)
REFILL_RATE 1 Tokens added per second (steady rate)
TTL_SECONDS 3600 Idle-bucket lifetime before TTL cleanup
MAX_RETRIES 5 Optimistic-lock retries before failing open
TABLE_NAME RateLimitTable Injected by CDK at deploy time

Clean up

npm run destroy

removalPolicy is DESTROY in this demo so the table is removed with the stack. Switch it to RETAIN before using this for anything real.

About

Serverless distributed rate limiter using the token bucket algorithm on DynamoDB, Lambda, and API Gateway — deployed with AWS CDK. TypeScript, ESM, Node 22, with atomic conditional writes and optimistic locking for correctness under concurrency.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages