logo
▼
Projects
Collaborations
Resources
Our Partners
Our Community
Projects
Collaborations
Resources
Our Partners
Our Community
Account
Sign InJoin UsHelp & Support

The Cometbid
Technology Foundation

Empowering innovation through open-source collaboration. TCTF supports developers, organizations, and communities worldwide in building the future of technology with transparent, vendor-neutral governance and world-class open-source projects.


Follow Us

Our Community

  • About Us
  • Upcoming Events
  • Projects
  • Collaborations
  • Membership
  • TCTF Training
  • Corporate Sponsorship

Learn

  • FAQ
  • TCTF Incubator Programs
  • Brand Guidelines
  • Logo Specifications

Legal

  • Privacy Policy
  • Terms of Use
  • Compliance
  • Code of Conduct
  • Contribution Guidelines
  • Legal & Trademark
  • Manage Cookies

More

  • Report a Vulnerability
  • Report Bugs
  • Mailing Lists
  • Contact Us
  • Support
  • Support Tickets
  • TCTF Social Network

Subscribe to our Newsletter

Caching Strategies for Serverless: From In-Memory to DynamoDB-Backed TTL Caches
Framework Deep DivesFramework Series #5

Caching Strategies for Serverless: From In-Memory to DynamoDB-Backed TTL Caches

Part 1 of the caching series — how we built a pluggable cache layer for TCTF with DynamoDB TTL caching, in-memory caching for Lambda warm starts, cache monitoring with health checks, and the interface that makes storage backends swappable.

June 20, 2026· 12 min read
TCTF Editorials
TCTF Newsletter
Home›Newsletter›Caching Strategies for Serverless: From In-Memo...

In This Edition

  • The Serverless Caching Challenge
  • The CacheService: One API, Multiple Backends
  • DynamoDB Cache: Zero Extra Infrastructure
  • In-Memory Cache: Fast but Volatile
  • TTL: The Serverless Cache Invalidation Strategy
  • Cache Monitoring and Health Checks
  • Choosing the Right Backend
3Storage Backends
DynamoDBDefault Backend
AutomaticTTL Expiration
YesBatch Operations
Built-inHealth Checks
DynamoDBZero Extra Infra

Caching in serverless is different from caching in traditional applications. There is no persistent process to hold an in-memory cache across requests. There is no Memcached cluster that the application server connects to on startup. Lambda functions are ephemeral — they spin up, handle a request, and may disappear. The cache must survive across invocations, across instances, and across cold starts. This article — Part 1 of a two-part series — covers the caching architecture we built for TCTF: a pluggable CacheService with DynamoDB-backed TTL caching as the default, in-memory caching for Lambda warm starts, and a monitoring layer that keeps the cache healthy. Part 2 covers ElastiCache Redis for sub-millisecond caching on hot paths.

01The Serverless Caching Challenge

In a traditional application, caching is straightforward. You spin up a Redis instance, connect to it from your application server, and cache frequently accessed data. The connection persists. The cache persists. Life is good.

In serverless, nothing persists. A Lambda function handles a request, and the next request might hit a completely different instance. In-memory caches reset on cold starts. Connection pools are recreated. Any state that lived in the process is gone.

This creates three requirements for a serverless cache. First, the cache must be external — stored in a service that every Lambda instance can access. Second, the cache must handle TTL (time-to-live) automatically — expired entries must be cleaned up without a background process. Third, the cache must be fast enough that the caching overhead does not exceed the cost of the original operation.

At TCTF, we also had a fourth requirement: the cache must be pluggable. Different services have different caching needs. Some need durability (geolocation data that is expensive to fetch). Some need speed (session lookups on every request). Some need simplicity (configuration data that rarely changes). One cache backend does not fit all.

🎯

Four requirements: external storage, automatic TTL, low overhead, and pluggable backends. One cache backend does not fit all 34 services.

The CacheService: One API, Multiple Backends

02The CacheService: One API, Multiple Backends

The CacheService is the single entry point for all caching operations across the platform. It exposes a clean, consistent API: get and set for single items, getMany and setMany for batch operations, delete and deleteMany for removal, has for existence checks, expire and getTtl for TTL management, getStats for monitoring, and clear for cache invalidation.

Every method works identically regardless of which storage backend is active. A service that caches geolocation data in DynamoDB uses the same API as a service that caches sessions in Redis. The caller never knows — or needs to know — which backend is handling the operation.

The CacheService is a singleton with lazy initialization. The first call to getInstance() creates the service and initializes the storage backend based on the CACHE_STORAGE_TYPE environment variable. Subsequent calls return the cached instance. This pattern is optimized for Lambda — the service is created once per warm instance and reused across invocations.

The storage backend can be changed at runtime via setCacheStorage(). This is used for testing (swap to in-memory during tests) and for graceful degradation (swap to DynamoDB if Redis becomes unavailable).

03DynamoDB Cache: Zero Extra Infrastructure

The DynamoDB cache backend is the default for TCTF services. It requires no additional infrastructure — it uses the service's existing DynamoDB table with a key prefix to separate cache entries from business data.

Each cache entry is stored as a DynamoDB item with four attributes: PK (the prefixed cache key), value (the JSON-serialized cached data), ttl (a Unix timestamp for automatic expiration), and createdAt (for monitoring and debugging). DynamoDB's built-in TTL feature automatically deletes items when their ttl timestamp passes — no cleanup jobs, no scheduled Lambda functions, no manual purging.

The DynamoDB cache supports all CacheService operations. Batch operations (getMany, setMany, deleteMany) use DynamoDB's BatchGetItem and BatchWriteItem for efficiency. The has operation uses a projection expression to check existence without reading the full item. The getStats operation scans the cache prefix to count entries and track hit/miss ratios.

Key prefixing prevents collisions. Every cache key is prefixed with a configurable string (e.g., CACHE#geo:, CACHE#config:). This means cache entries coexist safely with business data in the same table. The prefix is stripped on retrieval, so callers work with clean keys.

The DynamoDB cache is durable. If a Lambda function cold-starts, the cache is still there. If the service restarts, the cache is still there. The only way data leaves the cache is through explicit deletion or TTL expiration. This durability makes DynamoDB caching ideal for data that is expensive to fetch — geolocation lookups, external API responses, computed aggregations.

📦

DynamoDB caching requires zero extra infrastructure. It piggybacks on the service's existing table. TTL handles expiration automatically. The cache survives cold starts and restarts.

04In-Memory Cache: Fast but Volatile

The in-memory cache backend uses a JavaScript Map with TTL tracking. It is the fastest backend — no network calls, no serialization overhead, sub-microsecond access times. But it is volatile — the cache resets on every Lambda cold start.

The in-memory cache is useful for three scenarios. First, testing — unit tests run faster with in-memory caching than with DynamoDB or Redis. Second, per-invocation caching — data that is computed once per Lambda invocation and reused across multiple operations within that invocation (parsed configuration, validated schemas, resolved environment variables). Third, warm-start optimization — data that is cached in memory during a warm Lambda instance and repopulated from the external cache on cold start.

The in-memory cache implements the same ICacheStorage interface as DynamoDB and Redis. It supports TTL, batch operations, stats tracking, and key prefixing. A cleanup interval periodically removes expired entries to prevent memory growth in long-running Lambda instances with provisioned concurrency.

The maxSize configuration limits the number of entries. When the cache is full, the oldest entry is evicted (FIFO). This prevents unbounded memory growth — important in Lambda where memory is a billed resource.

⚡

In-memory cache: sub-microsecond access, zero network calls. But volatile — resets on cold start. Use for testing, per-invocation data, and warm-start optimization.

05TTL: The Serverless Cache Invalidation Strategy

Cache invalidation is famously one of the two hard problems in computer science. In serverless, TTL makes it manageable.

Every cache entry has a TTL — the number of seconds until the entry expires. When you call set(key, value, ttl), the cache backend stores the expiration timestamp. When you call get(key), the backend checks if the entry has expired. If it has, the entry is treated as a cache miss and the expired data is not returned.

DynamoDB handles TTL natively. Items with a ttl attribute are automatically deleted by DynamoDB's background process — typically within 48 hours of expiration, though the item is immediately invisible to reads once the timestamp passes. This means no cleanup code, no scheduled tasks, no manual purging.

The in-memory cache checks TTL on every get operation and runs a periodic cleanup to remove expired entries proactively. This prevents stale data from consuming memory.

TTL values are tunable per operation. Geolocation data gets a long TTL (24 hours) because IP-to-location mappings rarely change. Rate limit counters get a short TTL (60 seconds) matching the rate limit window. Configuration data gets a medium TTL (5 minutes) balancing freshness with read reduction. Session data gets a TTL matching the session expiration.

The CacheService also supports explicit TTL management. The expire method changes the TTL on an existing entry without re-setting the value. The getTtl method returns the remaining TTL in seconds. These are useful for extending session lifetimes and implementing sliding expiration windows.

06Cache Monitoring and Health Checks

A cache that fails silently is worse than no cache. If the DynamoDB cache starts returning errors, the service should fall back gracefully — not crash. The CacheMonitor provides the observability and resilience layer.

Health checks run on a configurable interval. The monitor writes a test key, reads it back, verifies the value, and deletes it. If the health check fails after the configured number of retries, it emits a CloudWatch metric and logs an error. The operations team sees the failure in the dashboard before users notice degraded performance.

The CacheMonitor integrates with the circuit breaker pattern. If the cache backend fails repeatedly, the circuit breaker opens and cache operations are skipped — the service operates without caching, hitting the source of truth directly. When the cache recovers, the circuit breaker closes and caching resumes automatically.

The getStats method on each storage backend returns hit count, miss count, and total keys. These metrics feed into CloudWatch dashboards that show cache hit rates per service. A dropping hit rate is an early warning sign — it might indicate TTL values that are too short, a cache that is too small, or a change in access patterns that the cache is not optimized for.

Graceful shutdown ensures cache connections are closed cleanly. For DynamoDB, this is a no-op (the client handles connection pooling). For Redis (covered in Part 2), this closes the connection and prevents leaks. For in-memory, this clears the cleanup interval.

📊

Health checks catch cache failures before users notice. Circuit breaker integration provides automatic fallback. Hit rate metrics in CloudWatch show cache effectiveness per service.

07Choosing the Right Backend

The pluggable architecture means every service can choose the caching strategy that fits its needs.

DynamoDB caching is the default and the right choice for most services. It requires no additional infrastructure, survives cold starts, handles TTL automatically, and provides single-digit millisecond latency. Use it for geolocation data, configuration caching, circuit breaker state, and any data where durability matters more than sub-millisecond speed.

In-memory caching is for per-invocation data and testing. Use it for parsed configurations, validated schemas, and any data that is cheap to recompute on cold start. Do not use it as a primary cache for data that must persist across invocations.

Redis caching (covered in Part 2) is for hot-path operations where sub-millisecond latency matters — session validation, rate limit counters, API response caching. It requires Lambda to run inside a VPC and adds operational complexity, so use it only when profiling shows that DynamoDB latency is a bottleneck.

The decision is not permanent. Start with DynamoDB caching. Monitor the hit rates and latency. If a service needs faster caching, switch to Redis by changing an environment variable. The code does not change. The API does not change. Only the performance characteristics change.

In Part 2, we cover ElastiCache Redis in detail — how to run Lambda inside a VPC, the Redis cache storage implementation, cluster mode support, and the specific use cases where Redis outperforms DynamoDB caching.

🎯

Start with DynamoDB (zero infra, durable, good enough for most services). Add Redis only when profiling shows the need. The pluggable interface makes the switch painless.

Article closing illustration

Caching in serverless is not about picking the fastest cache. It is about picking the right cache for each service — balancing speed, durability, operational complexity, and cost. The pluggable CacheService gives every TCTF service that choice without writing cache-specific code. DynamoDB for durability. In-memory for speed. Redis for the hot path. One interface, three backends, 34 services — each optimized for its own access patterns.

Editor's Note: This is Framework Series #5 in the TCTF Newsletter, Part 1 of the caching series. Part 2 covers ElastiCache Redis for sub-millisecond caching. Next: ElastiCache Redis for Low-Latency Session and API Caching.

Never miss an edition

Subscribe to get TCTF newsletters delivered to your inbox.

Subscribe
PreviousRate Limiting at Serverless Scale: Tiered Throttling with DynamoDB
NextCaching Strategies for Serverless, Part 2: ElastiCache Redis for Low-Latency Session and API Caching

In This Edition

  • The Serverless Caching Challenge
  • The CacheService: One API, Multiple Backends
  • DynamoDB Cache: Zero Extra Infrastructure
  • In-Memory Cache: Fast but Volatile
  • TTL: The Serverless Cache Invalidation Strategy
  • Cache Monitoring and Health Checks
  • Choosing the Right Backend

Browse by Month

May
  • The Struggles of Timelines and Schedules: When Building Gets Real
  • How to Stay Motivated in the Face of Uncertainties: Faith Beyond Doubt
  • Cognito Middleware: Building an Authentication Pipeline for Serverless APIs
  • Building TCTF's DynamoDB Query Framework, Part 1: Single-Table Design Patterns
April
  • Built to Last: Why Sustained Collaboration Is the Future of Tech Teams
  • Q2 2026 Roadmap: What's Next for the TCTF Portal
March
  • How We Built a Real-Time Messaging System with AWS Lambda and WebSockets
  • From Forum to Social Network: The Origin Story of Cometbid Social
  • Agentic AI: What It Means for Software Development and Why We're Paying Attention
February
  • Platform Update: Social Network Architecture, Achievement Engine, and What's Next
  • How We Built 34 Serverless Microservices: Architecture Patterns Behind the TCTF Platform
January
  • How We Secure the TCTF Platform: Principles Every Developer Should Know
  • New Year, New Projects: TCTF 2026 Roadmap

More From TCTF Newsletter

Built to Last: Why Sustained Collaboration Is the Future of Tech TeamsVol. 1, Issue 4

Built to Last: Why Sustained Collaboration Is the Future of Tech Teams

Most platforms optimize for transactions — post a job, hire, move on. TCTF is built around sustained collaboration: long-term teams, milestone-driven projects, language support that breaks barriers, and a community where everyone — not just developers — has a seat at the table.

April 15, 2026
Q2 2026 Roadmap: What's Next for the TCTF PortalQ2 2026

Q2 2026 Roadmap: What's Next for the TCTF Portal

Our quarterly roadmap for Q2 — what shipped in April, the origin of Cometbid Social, and the plan for May and June as we build toward user accounts, authentication, and the social network launch.

April 1, 2026
How We Built a Real-Time Messaging System with AWS Lambda and WebSocketsTech Series #3

How We Built a Real-Time Messaging System with AWS Lambda and WebSockets

Inside the architecture of TCTF's messaging platform — three services handling real-time chat, campaign delivery, and transactional notifications, all built on Lambda, API Gateway WebSockets, SQS, and multi-provider email with automatic failover.

March 15, 2026

Browse by Month

2026

May
  • The Struggles of Timelines and Schedules: When Building Gets Real
  • How to Stay Motivated in the Face of Uncertainties: Faith Beyond Doubt
  • Cognito Middleware: Building an Authentication Pipeline for Serverless APIs
  • Building TCTF's DynamoDB Query Framework, Part 1: Single-Table Design Patterns
April
  • Built to Last: Why Sustained Collaboration Is the Future of Tech Teams
  • Q2 2026 Roadmap: What's Next for the TCTF Portal
March
  • How We Built a Real-Time Messaging System with AWS Lambda and WebSockets
  • From Forum to Social Network: The Origin Story of Cometbid Social
  • Agentic AI: What It Means for Software Development and Why We're Paying Attention
February
  • Platform Update: Social Network Architecture, Achievement Engine, and What's Next
  • How We Built 34 Serverless Microservices: Architecture Patterns Behind the TCTF Platform
January
  • How We Secure the TCTF Platform: Principles Every Developer Should Know
  • New Year, New Projects: TCTF 2026 Roadmap