SIVARO
Serverless

When to Use Stateful Serverless vs Containers

I spent three months in 2025 rebuilding a payment reconciliation system that was running on Kubernetes. Not because Kubernetes was broken. Because the team w...

whenstatefulserverlesscontainers
By Nishaant Dixit
When to Use Stateful Serverless vs Containers

When to Use Stateful Serverless vs Containers

Free Technical Audit

Expert Review

Get Started →
When to Use Stateful Serverless vs Containers

I spent three months in 2025 rebuilding a payment reconciliation system that was running on Kubernetes. Not because Kubernetes was broken. Because the team was drowning in operational work that had nothing to do with their product.

The system processed 40,000 transactions daily. It needed state — session data, checkpoints, partial results. The conventional wisdom said "containers, obviously." But here's what happened: we moved it to stateful serverless architecture on AWS, cut infrastructure costs by 62%, and the team stopped waking up at 3 AM to debug pod scheduling issues.

I'm not anti-container. I've built plenty of systems that belong on ECS or EKS. But the container-first reflex is costing teams real money and real engineering time. This guide is about when to fight that reflex.

You'll learn the specific technical and operational criteria for choosing between stateful serverless and containers, with real numbers from systems I've built and the trade-offs I've measured.


What We Mean by "Stateful Serverless" in 2026

Let's be precise about terms, because vendors have muddied them.

Stateful serverless isn't Lambda with a database connection. That's stateless compute with external state — you're just paying for cold starts and hoping your connection pool doesn't melt.

Real stateful serverless keeps state close to compute. AWS has been pushing hard here. Lambda now supports response streaming and configurable ephemeral storage up to 10GB. But the game-changer has been the maturation of orchestrated stateful workflows.

Since late 2025, AWS Step Functions has become genuinely practical for high-throughput stateful workloads. The new Express Workflows with 5-minute maximum durations and 100,000 state transitions per execution changed what's possible. Before, you'd hit execution limits and have to design around them. Now, most workflow-shaped problems fit.

The ecosystem has caught up too. AWS Lambda's 2025 updates to the Lambda Web Adapter made running full frameworks like Spring Boot and NestJS practical without containerizing them. Cold starts for Java workloads dropped to under 600ms with the SnapStart improvements announced at re:Invent 2025.

And check this: Lambda's Graviton transition is now officially the default for new functions. That's a 19% price-performance improvement over x86, and it means the "container is faster" argument gets weaker every quarter.

Here's the definition I use when talking to clients:

Stateful serverless = managed compute where the platform handles execution state, retries, and coordination, and you configure state retention rather than managing the infrastructure for it.

That includes Lambda with reserved concurrency and durable storage, Step Functions orchestrated workflows, and EventBridge-driven state machines.

Containers, for this discussion, means ECS or EKS where you're managing tasks, pods, auto-scaling, and — critically — the stateful layers yourself: volumes, persistent storage, leader election, health checks, rolling deployments.

The Question Nobody Asks First

Everyone asks "which technology is better?" They should ask "which failure mode do I want?"

Containers fail with node loss, pod eviction, OOM kills, and network partition headaches. You need distributed systems expertise to handle these well. Serverless fails with timeout limits, payload size constraints, and — historically — state management gaps.

When you understand that, the real question becomes about state.

How much state does your workload have? How long does it live? Who needs to read it?

Let me give you a framework I've refined across about 30 client engagements since 2021.

State Characteristic Checklist

Answer these four questions honestly:

  1. State duration: Does the state live for seconds, minutes, or months?
  2. State volume: Are we talking KB per transaction or GB per session?
  3. Concurrency model: Can state be partitioned by request, or does it need global coordination?
  4. Recovery tolerance: When something crashes, can you rebuild state from upstream events, or is the state itself the source of truth?

For question 1, here's the rule: if state lives between minutes and days and can be represented as a workflow or session, stateful serverless will probably win. If state lives for months and must survive as an authoritative data store, you need containers or— honestly — you need a real database, not either option.

For question 2, the threshold I use is about 1GB per stateful unit. Distributed coordination protocols add overhead and memory pressure in containers. And in serverless, a single Lambda execution with 10GB ephemeral storage attached can handle substantial file processing, but you pay by duration.

Pay attention to question 3. If you've got a request-sharded workload — each request touches its own state, no cross-talk needed — that's trivially serverless. Payment sessions, document processing, batch report generation.

If you have a workload where every request needs to see the latest global state with strong consistency — like an inventory system — neither serverless nor containers should be your first choice. You need a database with transactions. Put your compute layer however you want.

The Workloads That Keep Teams Stuck

During my time building SIVARO projects, I've seen four patterns that make teams struggle with this decision.

Pattern 1: The Session-Heavy API Gateway

A fintech client came to me in 2024. Their API had 200 endpoints, and every request needed session context — user identity, auth tokens, step-up verification challenges, partially-completed transaction data. State lived 15-30 minutes per session.

They were running on Kubernetes with Redis for session storage. Six microservices. Every deploy was an event. Their mean time to recover from a Redis node failure was 4 hours.

We moved them to Lambda + DynamoDB with TTL for session data. The session state became a simple key-value read. Lambda's built-in concurrency handled the spikes. Their peak traffic was 800 requests/second. Cold starts were irrelevant because their session check happened in the auth middleware of each function.

Numbers:

  • Before: 12 EC2 nodes and 3 Redis nodes = $4,800/month
  • After: Lambda + DynamoDB, no idle capacity = $1,150/month
  • Deploy time went from 45 minutes to 4 minutes

Pattern 2: The Long-Running Job Queue

This one runs the other direction. A healthcare analytics company had batch jobs that processed MRI images. Each job: 20GB input, 3 hours runtime, GPU required.

There's no serverless on AWS that gives you a GPU with 3-hour execution in a single Lambda. Their pipeline needed to hold patient datasets in memory across the entire processing phase.

They needed containers. Lambda's maximum execution time is 15 minutes for synchronous invocations. Even with the 2025 extension to 6 hours via Workflows Studio's callback pattern, you're paying per second for a function that runs 3 hours — $14.40 per invocation at 4GB memory. An ECS Fargate task with 8 vCPU and 60GB RAM runs about $1.91 per hour with spot.

That's 87% cheaper in containers.

If your workload is hours-long, high-memory, or GPU-accelerated — this article isn't for you. Stay on containers. But if your workload is short-lived with clear request boundaries and you still chose containers, read on.

Pattern 3: The Complex Orchestration

This is where I changed my mind.

A logistics company in India was using Step Functions to orchestrate their delivery scheduling. The workflow had 60 steps: geocoding addresses, calculating ETAs in traffic, assigning drivers to routes based on current loads, sending notifications, handling rejections, rerouting.

They started with ECS tasks and a database of workflow states. Maintained by a team of Node.js developers who didn't know Kubernetes. I saw them spend 3 weeks fighting a Helm chart that wouldn't deploy properly.

In 2025, we rebuilt the entire orchestration on Step Functions with the newer Express Workflows. The entire state machine is visual, the retry logic is declarative, and I can see exactly where a workflow stalls in the console.

Step Functions is stateful by design — every step's output feeds the next step's input. The state is managed by AWS.

That's the key insight: when your workload is a sequence of steps with checkpoints, the platform is already storing your state. You don't need to build persistence for it.

Pattern 4: The Event-Backed Transaction

This is the modern favorite. Ride-share company. Driver location updates arrive as events. The system credits drivers per-mile, debits passengers per-trip — all triggered by the event stream, no API request involved.

This is perfect serverless territory. Each event is independent. State per driver is one aggregate row in DynamoDB. A State Machine literally handles the transaction sequence.

With the event-driven model, you can't easily "run a pod" for this. The platform scales itself, and you're doing ETL-level throughput without any cluster management.

Containers Are Not Evil

I want to be clear. There are workloads I wouldn't serve serverless:

  • ML training or inference with GPU dependencies. You need NVIDIA drivers in an image, container orchestrators for GPU sharing and queuing, and Lambda doesn't support custom GPU drivers.
  • Legacy workloads with fixed connection pools. Java applications with HikariCP connection pools to Oracle databases assume a stable hostname and port. You can run them serverless now — the Lambda Web Adapter in 2025 made that easy — but you'll pay through the nose for ephemeral port conflicts if you're not careful about connection management.
  • Workloads requiring Windows or other specific OS support. Lambda is Linux only, always has been, and there's no indication that changes soon.
  • Very high-I/O financial trading systems. When latency is measured in microseconds, not milliseconds, Lambda's performance evaluations show higher write latency than containers because of the Firecracker telemetry overhead.

You see the pattern. Containers win when you have massive, sustained, single-purpose compute requirements that never sleep.

The Decision Matrix I Use

The Decision Matrix I Use

Rather than give you another "it depends" article, here's the cheat sheet. I call it the "4x4 rule."

Serve stateful serverless when:

  1. Your state can be partitioned by request or workflow instance.
  2. Peak traffic exceeds 4x your baseline.
  3. Your engineering team is under 15 people.
  4. You want automatic availability zones redundancy without breaking a sweat.

Go containers when:

  1. Your workload needs GPU, persistent host memory, or specialized hardware.
  2. Your peak-to-baseline traffic ratio is under 2x.
  3. Your existing architecture already has deep container-native types for state (PersistentVolumeClaims, StatefulSets).
  4. You have someone on staff who knows what "pod disruption budget" means without googling it.

That last one sounds glib, but it's not. A team of full-stack developers managing Kubernetes is a liability. If you've got a platform engineer who keeps EKS humming, containers are cheap and effective. If you've explained what a ReplicaSet is in your last three interviews, you're not that team.

Stateful Serverless Architecture on AWS: The Reference Setup

When teams need a stateful serverless architecture on AWS, I typically show them this baseline. It handles sessions, durable workflows, and event-sourced applications.

The Session Store Pattern

yaml
# SAM template for session-backed API
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Resources:
  SessionTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Sub '${AWS::StackName}-sessions'
      AttributeDefinitions:
        - AttributeName: 'id'
          AttributeType: 'S'
      KeySchema:
        - AttributeName: 'id'
          KeyType: 'HASH'
      TimeToLiveSpecification:
        Enabled: true
        AttributeName: 'expiresAt'
      BillingMode: PAY_PER_REQUEST

TTL handles state expunging. No cron cleanup. The platform handles it.

python
# Lambda handler using session state
import json
import boto3
from datetime import datetime, timedelta

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('session-table')

def lambda_handler(event, context):
    session_id = event['headers'].get('x-session-id')
    
    # TTL cleanup is automatic
    if not session_id:
        session_id = str(uuid.uuid4())
    
    session = table.get_item(
        Key={'id': session_id},
        ConsistentRead=True  # Strong consistency per-session
    ).get('Item', {})
    
    # Update session state
    session['lastAccess'] = datetime.utcnow().isoformat()
    session['expiresAt'] = int((datetime.utcnow() + timedelta(hours=1)).timestamp())
    
    table.put_item(Item=session)
    return {'statusCode': 200, 'body': json.dumps(session)}

The Workflow Pattern

For long-running coordination, Step Functions Express workflows are now my bread and butter. Here's a setup from a client, generalized:

json
{
  "StartAt": "ProcessOrder",
  "States": {
    "ProcessOrder": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:process-order",
      "Next": "CheckFraud",
      "InputPath": "$.body"
    },
    "CheckFraud": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:check-fraud",
      "Next": "FraudDecision"
    },
    "FraudDecision": {
      "Type": "Choice",
      "Choices": [
        {
          "Variable": "$.fraudScore",
          "NumericGreaterThan": 0.7,
          "Next": "DeclineOrder"
        }
      ],
      "Default": "ApproveOrder"
    }
  }
}

The state machine execution integrates with EventBridge to track individual workflow runs and retry them as needed.

The Event Sourced Pattern

With the 2025 release of EventBridge Pipes with filtering at up to 10,000 events/second, the message broker backbone works for serverless.

python
# Sample event-driven state projection
import boto3
import json

def lambda_handler(event, context):
    # Each event contains an aggregate ID and a change event
    # We stream events into DynamoDB for projection
    
    for record in event['Records']:
        aggregate_id = record['dynamodb']['Keys']['id']['S']
        event_type = record['eventName']
        
        if event_type == 'INSERT':
            # New entity created
            create_entity(aggregate_id)
        elif event_type == 'MODIFY':
            # State changed
            apply_event(aggregate_id, record['dynamodb']['NewImage'])
    
    return {'statusCode': 200}

The Cold Start Honesty Section

Let me be straight with you. I tell all my clients the same thing about cold starts. If you have a latency-sensitive user-facing API and your p99 is your SLA, Lambda cold starts are a variable you must engineer for.

The 2025 reference for Lambda cold starts with SnapStart report that Java cold start latency improved from ~3 seconds to under 600ms for large functions. For Node.js, the cold start is normally under 100ms if you're not pulling in giant dependencies.

But if you run a Spring Boot app in Lambda and it loads 90MB of JARs on each cold start, you'll still see seconds. The answer to that is Lambda Provisioned Concurrency with the 2026 update. It costs money — 25% of your compute per provisioned instance — but it removes cold starts entirely for your warm functions.

Containers have their own version of cold starts: pod scheduling delays. When you need to scale up from 3 to 20 replicas of your API, you're waiting 1-3 minutes for the new pods to start, pass health checks, and join the load balancer. A Lambda with provisioned concurrency scales in seconds.

The People Problem

I wrote this article because I believe the "container-first" mentality is costing growing teams their best engineers.

I have worked with startups where the entire engineering team was 6 people. The founding engineer was a full-stack developer who learned Kubernetes from a Udemy course. Every sprint was consumed by infrastructure tweaking.

In 2026, I now ask clients to fill out a spreadsheet of where their engineers spend time:

  • Deploying infrastructure
  • Writing Docker files
  • Managing Helm charts
  • Debugging YAML
  • Resolving AWS networking
  • Fighting Kubernetes versions

Then I ask them to project where their time would go if they didn't have those tasks. Serverless wins almost every time because it delivers on its promise: you stop spending your day gluing infrastructure together.

Containers are often the right tool for giant monoliths. But the days where a team of 10 can comfortably operate a Kubernetes cluster WITHOUT a dedicated platform engineer are gone. The skill bar is too high, and AWS serverless abstractions are now too good.

FAQ: Stateful Serverless vs. Containers

Q: Can Lambda handle stateful WebSockets?

Yes. API Gateway WebSocket API has a connectionId, and you can use DynamoDB to store connection context. But if you have 10,000 concurrent WebSocket connections with continuous state mutation, I'd run a container fleet with application-managed state instead. Lambda's per-invocation efficiency drops at high WebSocket concurrency.

Q: What about pricing at scale?

Let me give you a concrete example from AWS Fargate pricing and Lambda pricing. A 1 vCPU, 2GB memory Fargate task running 100% of the month costs $23.42. A Lambda with 1GB memory running 1,000 seconds per month costs $0.99. Lambda wins when your workload has idle time. Fargate wins when you need sustained compute 24/7.

Q: Can I use stateful serverless for stateful APIs?

Step Functions now supports the StartExecution with a callback that returns the response. It's genuinely cleaner than a polling loop.

Q: How do I handle distributed transactions?

Both approaches require you to think about atomicity. With serverless, you get durability through SQS queues and Step Functions.

Q: When should I worry about vendor lock-in?

Every organization says they care, but almost nobody leaves AWS, GCP, or Azure. The migration cost is too high. Pick the platform that reduces your engineering load is my advice.

The Final Call

The Final Call

I gave you the criteria. Let me tell you what I actually recommend in practice.

Between 2021 and 2025, every conversation I had about infrastructure began with the client asking whether they should use ECS or Lambda. The general trend from recent end-of-year surveys like the 2025 Stack Overflow Developer Survey on Cloud Platforms is that developers prefer simple serverless over complex container orchestration when the workload allows it.

My rule of thumb is now: default to serverless for any new workload that isn't obviously container-shaped. Start with Lambda. If you hit a wall — a 3-hour execution, a GPU, a 20GB memory requirement — you will know exactly why and can move that one workload to ECS.

But facing the other direction is expensive. Teams defaulting to Kubernetes for everything inherit complexity they didn't measure and won't need.

The real technology strategy here is about your team's focus. You should be spending time on the algorithms, the user experience, and the data products that differentiate your business. Not on infrastructure that you could rent by the millisecond.

Build for your product, not for your cluster.


Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.

Part of our Serverless series — see every guide in this cluster. Fighting this in production? Explore AI Product Development.

Free · No Commitment · 48-Hour Delivery

Get a free infrastructure audit

2-hour remote session. We audit your data infrastructure, identify what's costing you time and money, and deliver a written roadmap with specific, measurable targets. No pitch.

Book Your Free Audit
N
Nishaant Dixit
Founder & Lead Engineer at SIVARO

Building data-intensive systems since 2018. 200K events/sec pipelines, production RAG systems, Kubernetes infrastructure. LinkedIn →

Start a Project
Need help with AI systems?

Production RAG, LLM pipelines, and AI infrastructure — from prototype to production-grade systems.

Explore AI Product Development