ESC
Type to search guides, tutorials, and reference documentation.
Verified by Garnet Grid

Serverless Architecture Patterns

Design scalable applications with serverless computing. Covers function composition, event-driven architectures, cold start optimization, serverless API design, fan-out/fan-in patterns, and the patterns that make serverless production-ready.

Serverless computing eliminates infrastructure management: no servers to provision, no capacity to plan, no patches to apply. Functions run on demand, scale automatically, and you pay only for execution time. But serverless introduces its own complexity: cold starts, distributed state, vendor lock-in, and debugging challenges.


When Serverless Fits

Good fit:
  ☑ Event-driven workloads (webhooks, notifications)
  ☑ Variable traffic with unpredictable spikes
  ☑ Low-traffic APIs (pay-per-use saves money)
  ☑ Data processing pipelines (file uploads, ETL)
  ☑ Scheduled tasks (cron jobs)
  
Poor fit:
  ☒ Long-running processes (>15 min on AWS Lambda)
  ☒ High-throughput, steady-state workloads (containers are cheaper)
  ☒ Low-latency requirements (<50ms, cold starts are a problem)
  ☒ Stateful applications (WebSockets, gaming)
  ☒ Heavy compute (ML training, video encoding)

Patterns

Fan-Out/Fan-In:
  S3 Upload → Lambda splits file into chunks
              → Lambda processes chunk 1
              → Lambda processes chunk 2
              → Lambda processes chunk 3
              → SQS collects results → Lambda aggregates

API Composition:
  API Gateway → Lambda: /users     → DynamoDB
              → Lambda: /orders    → DynamoDB
              → Lambda: /payments  → Stripe API
              → Lambda: /reports   → S3

Event Processing:
  Kinesis Stream → Lambda filters → DynamoDB
                 → Lambda enriches → ElasticSearch
                 → Lambda archives → S3

Saga (Distributed Transaction):
  Step Function:
    1. Lambda: Reserve inventory    → Success → Continue
    2. Lambda: Charge payment       → Success → Continue
    3. Lambda: Create shipment      → Failure → Compensate
    Compensate:
      3c. Lambda: Refund payment
      2c. Lambda: Release inventory

Cold Start Optimization

# Cold start: First invocation after idle period
# AWS Lambda cold start: 100ms-10s depending on runtime and package size

# BEFORE: Slow cold start (5+ seconds)
import boto3
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier

def handler(event, context):
    # All imports loaded every cold start
    ...

# AFTER: Optimized cold start

# 1. Use lighter runtime (Node.js/Python > Java/C#)
# 2. Minimize package size
# 3. Lazy load heavy dependencies

import json  # Light import at module level

def handler(event, context):
    # Only import heavy libraries when actually needed
    if event.get("needs_ml"):
        import sklearn  # Lazy load
    
    # Reuse connections between invocations
    # (module-level = persists across warm invocations)
    ...

# Module-level initialization (runs once per cold start)
import boto3
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('users')  # Connection reused across invocations

# 4. Provisioned concurrency for critical functions
# AWS: Keep N instances warm at all times
# Cost: ~$0.000004463 per GB-second provisioned

Cost Model

Lambda pricing (AWS):
  Per request: $0.20 per 1M requests
  Per compute: $0.0000166667 per GB-second
  
  Example: API with 10M requests/month, 256MB, 200ms avg
  Requests: 10M × $0.20/1M = $2.00
  Compute:  10M × 0.2s × 0.25GB × $0.0000166667 = $8.33
  Total:    $10.33/month
  
  Same workload on EC2 (t3.medium, always-on):
  Monthly: $30.37
  
  Serverless is 66% cheaper for this workload!
  
  But: At 100M requests/month (steady traffic):
  Lambda: $103.33/month
  EC2:    $30.37/month (can handle the load)
  
  Containers become cheaper at steady, high-volume traffic.

Anti-Patterns

Anti-PatternConsequenceFix
Monolith in a LambdaHuge package, slow cold startSmall, focused functions
Synchronous chainsFragile, cascading timeoutsEvent-driven, async communication
No timeout configurationFunction runs until platform maxSet timeout per function based on expected duration
Shared mutable stateRace conditions, data corruptionExternal state store (DynamoDB, Redis)
No dead letter queueFailed events silently lostDLQ for every async invocation source

Serverless is not about eliminating servers — it is about eliminating server management. The trade-off: less infrastructure work, more application architecture complexity. Choose serverless when the trade-off works in your favor.

Jakub Dimitri Rezayev
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting

Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.

View Full Profile →