Back to Lambda & Serverless
Q2Question 2 of 2

Common Serverless Patterns and When Serverless Is Not a Good Fit

Key Concepts
  • API Gateway plus Lambda plus DynamoDB is the standard serverless CRUD pattern that scales to zero and bills per request.
  • Step Functions orchestrates multi-step workflows with built-in state, retries, error handling, and visual debugging.
  • EventBridge is a serverless event bus that decouples producers from consumers through event rules and fan-out.
  • SQS plus Lambda handles async processing with durable buffering, automatic scaling, and dead-letter queues for failures.
  • Serverless is a poor fit for tasks exceeding fifteen minutes, sustained heavy compute, and long-lived stateful connections.
  • These patterns compose into one system: sync API, async processing, event-driven fan-out, and orchestrated workflows together.

Definition

Serverless patterns are API Gateway plus Lambda plus DynamoDB for CRUD, Step Functions for workflows, EventBridge for event routing, and SQS plus Lambda for async work; avoid serverless for long-running, heavy-compute, or long-lived stateful connection workloads.
  • API Gateway + Lambda + DynamoDB – the standard serverless CRUD pattern: API Gateway receives HTTP, Lambda runs logic, DynamoDB stores data, all scaling to zero.
  • Step Functions – orchestrates multi-step workflows as a state machine with built-in retries, error handling, and visual execution history.
  • EventBridge – a serverless event bus that routes events from producers to consumers by matching rules, decoupling services.
  • SQS + Lambda – async processing pattern: a durable queue buffers work, Lambda scales consumers with the backlog, and a dead-letter queue catches failures.
  • Not a fit – long-running tasks (exceeding fifteen minutes), sustained heavy compute (cheaper always-on), and long-lived stateful connections (WebSocket in-process state).

Think of these as proven floor plans for departments at National Bank of India. API Gateway plus Lambda plus DynamoDB is the quick-service counter: a customer asks, a clerk appears only for that request, serves it, and leaves. Step Functions is the loan-approval workflow pinned on the wall: step one check documents, step two credit check, step three approve or reject, with clear arrows and "if this fails, do that." EventBridge is the internal announcement system: when "payment received" is announced, every interested department hears it and reacts. SQS plus Lambda is the in-tray: forms pile up safely and clerks process them steadily.

Understanding the Concepts

What is the API Gateway plus Lambda plus DynamoDB pattern?

This is the backbone of simple serverless APIs. API Gateway receives the HTTP request, handles authentication and throttling, and invokes a Lambda function. The function runs business logic and reads or writes DynamoDB, a serverless NoSQL store that scales automatically. Nothing is provisioned when idle, and it scales with traffic.

JAVA
// Lambda handler behind API Gateway doing a DynamoDB write
package com.bank.lambda;

import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;
import java.util.Map;

public class CreateAccountHandler {
    private static final DynamoDbClient dynamo = DynamoDbClient.create();

    public Map<String, Object> handleRequest(Map<String, Object> apiEvent, Object ctx) {
        String accountId = "SAV" + System.currentTimeMillis();
        dynamo.putItem(PutItemRequest.builder()
            .tableName("nbi-accounts")
            .item(Map.of(
                "accountId", AttributeValue.fromS(accountId),
                "customerName", AttributeValue.fromS("Rajesh"),
                "balance", AttributeValue.fromN("50000")))
            .build());
        return Map.of("statusCode", 201, "body", "{\"accountId\":\"" + accountId + "\"}");
    }
}

What is Step Functions for workflow orchestration?

Instead of one giant Lambda doing many steps with tangled error handling, you define a state machine where each state calls a Lambda or an AWS service. Step Functions manages the sequence, parallel branches, retries with backoff, timeouts, and catch rules. The workflow is visible, durable, and auditable.

JAVA
// Step Functions workflow concept: loan approval
package com.bank.workflow;

public class LoanApprovalWorkflow {
    public static void printSteps() {
        System.out.println("Step 1: ValidateDocuments (Lambda)");
        System.out.println("  - If missing docs -> REJECT");
        System.out.println("Step 2: CreditCheck (Lambda)");
        System.out.println("  - If score < 600 -> REJECT");
        System.out.println("  - Retry on timeout with exponential backoff");
        System.out.println("Step 3: CalculateEMI (Lambda)");
        System.out.println("Step 4: Approve or Reject (Choice state)");
        System.out.println("Step 5: NotifyCustomer (Lambda)");
        System.out.println();
        System.out.println("State machine tracks each execution with full history.");
    }
}

What is EventBridge for event-driven architecture?

EventBridge is a serverless event bus. Producers publish events, and rules match events by source, type, or content and route them to targets like Lambda, SQS, or Step Functions. This decouples producers from consumers: a "PaymentReceived" event fans out to the ledger, the notifier, and fraud scoring independently, and adding a new consumer requires only a new rule, not changing the producer.

JAVA
// Publishing an event to EventBridge
package com.bank.events;

import software.amazon.awssdk.services.eventbridge.EventBridgeClient;
import software.amazon.awssdk.services.eventbridge.model.*;
import java.util.List;

public class PaymentEventPublisher {
    private final EventBridgeClient eb = EventBridgeClient.create();

    public void publishPaymentReceived(String txnId, String amount) {
        eb.putEvents(PutEventsRequest.builder()
            .entries(List.of(
                PutEventsRequestEntry.builder()
                    .source("com.bank.payments")
                    .detailType("PaymentReceived")
                    .detail("{\"txnId\":\"" + txnId + "\",\"amount\":\"" + amount + "\"}")
                    .build()))
            .build());
    }
}

What is SQS plus Lambda for async processing?

Work is placed on an SQS queue, which durably stores messages. Lambda consumes the queue as an event source, scaling the number of concurrent executions with the message backlog. If a message fails repeatedly, it goes to a dead-letter queue (DLQ) for inspection. This decouples the producer from a slower consumer and smooths traffic spikes.

JAVA
// Lambda consuming SQS messages
package com.bank.lambda;

import com.amazonaws.services.lambda.runtime.events.SQSEvent;
import java.util.List;

public class StatementGeneratorHandler {
    public void handleRequest(SQSEvent event, Object context) {
        List<SQSEvent.SQSMessage> messages = event.getRecords();
        for (SQSEvent.SQSMessage msg : messages) {
            String accountId = msg.getBody();
            System.out.println("Generating statement PDF for: " + accountId);
            // Generate PDF -> upload to S3
        }
    }
}

When is serverless NOT a good fit?

Serverless is a poor fit for three categories. First, long-running tasks that exceed Lambda's fifteen-minute limit -- a forty-minute reconciliation must be a container or be split into Step Functions steps. Second, heavy, sustained compute: if a function runs flat out around the clock, always-on instances are cheaper than per-millisecond billing. Third, workloads needing long-lived stateful connections held in-process; while API Gateway supports managed WebSockets, holding many persistent connections with large in-memory state fights the stateless, short-lived model.

JAVA
// When to avoid serverless
package com.bank.infrastructure;

public class ServerlessAntiPatterns {
    public static void main(String[] args) {
        System.out.println("NOT serverless:");
        System.out.println("  1. 40-min reconciliation batch (exceeds 15-min limit)");
        System.out.println("  2. 24/7 high-CPU fraud engine (always-on is cheaper)");
        System.out.println("  3. Real-time trading with persistent connections");
        System.out.println();
        System.out.println("USE serverless:");
        System.out.println("  1. Statement PDF generation (spiky, event-driven)");
        System.out.println("  2. CRUD API with variable traffic (scales to zero)");
        System.out.println("  3. Event fan-out (payment triggers multiple consumers)");
    }
}

How do these patterns compose into a real system?

A real banking system uses multiple serverless patterns together. The synchronous API uses API Gateway plus Lambda plus DynamoDB. Domain events flow through EventBridge. Async side effects are processed via SQS plus Lambda. Multi-step business processes run as Step Functions state machines. The skill is knowing which pattern fits each piece of the system.

JAVA
// Composing serverless patterns in one system
package com.bank.infrastructure;

public class ComposedServerlessArchitecture {
    public static void main(String[] args) {
        System.out.println("NBI Payments Platform (Serverless):");
        System.out.println("  Sync API:    API Gateway -> Lambda -> DynamoDB");
        System.out.println("  Events:      Lambda publishes PaymentReceived to EventBridge");
        System.out.println("  Async:       EventBridge -> SQS -> Lambda (statement generation)");
        System.out.println("  Workflow:    API Gateway -> Step Functions (loan approval)");
        System.out.println("  Non-serverless: ECS task for nightly reconciliation batch");
    }
}

What are common mistakes with serverless patterns?

The first mistake is using Lambda for everything, including long-running and steady workloads where containers are cheaper and more appropriate. The second is building long synchronous chains of Lambdas calling Lambdas, which is both slow and expensive. The third is ignoring dead-letter queues on SQS, losing failed messages silently. The fourth is not setting a concurrency limit, allowing a runaway event to consume all Lambda concurrency in the account.

JAVA
// Wrong: Lambda calling Lambda synchronously (chain)
// Slow, expensive, and fragile

// Correct: decouple with SQS or EventBridge
// Lambda A -> SQS -> Lambda B (async, decoupled, retryable)
// Lambda A -> EventBridge -> Lambda B, Lambda C (fan-out)

What should a senior engineer know?

Senior engineers understand that serverless is an architecture pattern, not a binary choice. The same system uses serverless where workloads are event-driven and bursty, and containers where they are long-running and steady. They size Lambda memory using the AWS Lambda Power Tuning tool, they set reserved concurrency to prevent one function from starving others, and they use Step Functions Express Workflows for high-volume, short-duration orchestrations where Standard Workflows would be too expensive.

Visual Overview

DIAGRAM
          Common Serverless Patterns

  1. API Gateway + Lambda + DynamoDB (Sync CRUD)
  ┌────────┐    ┌────────┐    ┌────────────┐
  │ Client │───→│API GW  │───→│  Lambda    │───→ DynamoDB
  └────────┘    │(auth,  │    │(logic)     │
                │throttle│    └────────────┘
                └────────┘

  2. Step Functions (Workflow Orchestration)
  ┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
  │ Validate │──→│ Credit   │──→│ Calculate│──→│ Approve/ │
  │ Docs     │   │ Check    │   │ EMI      │   │ Reject   │
  └──────────┘   └──────────┘   └──────────┘   └──────────┘
                  retry on               choice
                  timeout                state

  3. EventBridge (Event-Driven Fan-Out)
                 ┌─────────────┐
  PaymentReceived│ EventBridge │───→ Lambda (update ledger)
  ──────────────→│ (event bus) │───→ Lambda (send notification)
                 │             │───→ Lambda (fraud scoring)
                 └─────────────┘

  4. SQS + Lambda (Async Processing)
  ┌──────────┐    ┌───────┐    ┌──────────┐
  │ Producer │───→│  SQS  │───→│  Lambda  │
  │          │    │(buffer│    │(consumer)│
  └──────────┘    │ retry)│    └──────────┘
                  └───┬───┘         │
                      │ failures    │
                      ▼             │
                  ┌───────┐         │
                  │  DLQ  │←────────┘
                  └───────┘

Key Takeaway

Serverless patterns are proven architectures built from managed, scale-to-zero services, and I combine them based on the shape of each piece of work. API Gateway plus Lambda plus DynamoDB is my go-to for simple CRUD APIs: everything scales with traffic and costs nothing when idle. Step Functions orchestrates multi-step workflows like loan approval with durable state, built-in retries, and explicit error paths. EventBridge is my event bus for decoupling producers from consumers through event rules and fan-out. SQS plus Lambda is my async-processing pattern with durable buffering and dead-letter queues for failures.

Just as important is knowing when serverless is the wrong fit. It is poor for long-running tasks exceeding fifteen minutes, for sustained heavy compute where always-on is cheaper, and for workloads that need long-lived stateful connections with large in-memory state.

The senior point I stress is that these patterns compose into one system rather than competing. The same banking platform uses API Gateway plus Lambda for the sync API, EventBridge for event fan-out, SQS plus Lambda for async processing, Step Functions for business workflows, and ECS containers for batch jobs that exceed serverless limits.

At National Bank of India I built the payments platform exactly this way. Customers submitted payments through API Gateway plus Lambda plus DynamoDB. Each payment published an event to EventBridge that fanned out to the ledger, notifier, and fraud scoring independently. Statement generation went onto SQS plus Lambda. The loan-approval process ran as a Step Functions state machine with retries and error paths. The nightly reconciliation batch, which exceeds fifteen minutes and saturates CPU, ran as an ECS container -- the honest boundary where serverless stops being the right tool.

Remember one sentence: serverless patterns compose -- sync CRUD with API Gateway plus Lambda, async with SQS plus Lambda, events with EventBridge, workflows with Step Functions -- and the skill is knowing where to draw the line and use containers instead.

---

Share
Use ← → arrow keys to navigate