惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
Project Zero
Project Zero
K
Kaspersky official blog
G
Google Developers Blog
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
Cyberwarzone
Cyberwarzone
Y
Y Combinator Blog
Recorded Future
Recorded Future
Blog — PlanetScale
Blog — PlanetScale
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cisco Talos Blog
Cisco Talos Blog
Latest news
Latest news
Microsoft Security Blog
Microsoft Security Blog
H
Help Net Security
S
Schneier on Security
P
Palo Alto Networks Blog
H
Hacker News: Front Page
N
News and Events Feed by Topic
N
Netflix TechBlog - Medium
博客园 - Franky
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
SecWiki News
SecWiki News
Cloudbric
Cloudbric
TaoSecurity Blog
TaoSecurity Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The Hacker News
The Hacker News
C
Check Point Blog
L
LangChain Blog
腾讯CDC
小众软件
小众软件
T
Tenable Blog
Google DeepMind News
Google DeepMind News
GbyAI
GbyAI
L
LINUX DO - 最新话题
A
About on SuperTechFans
Google Online Security Blog
Google Online Security Blog
C
Cisco Blogs
Recent Announcements
Recent Announcements
Hacker News: Ask HN
Hacker News: Ask HN
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Vercel News
Vercel News
雷峰网
雷峰网
美团技术团队
D
DataBreaches.Net
Martin Fowler
Martin Fowler
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
F
Full Disclosure
博客园_首页

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Lambda Durable Functions, When You Don't Need Step Functions
Lewis Sawe · 2026-05-13 · via DEV Community

At re:Invent 2025, AWS added a new primitive to Lambda called durable execution. Your function can now checkpoint its progress, survive failures without restarting from scratch, and suspend for up to a year without paying for compute time.

If you've used Azure Durable Functions or Temporal, the concept is familiar. If you haven't, the short version is that your Lambda function can pause mid-execution, wait for something external (a human approval, a webhook, a scheduled delay), and resume exactly where it left off. No DynamoDB state table. No Step Functions state machine. Just code.

This post covers what it is, how it works, when to use it instead of Step Functions, and what it actually looks like to build with.

The Problem It Solves

Standard Lambda functions run from start to finish in a single invocation. Maximum 15 minutes. If something fails at step 7 of 10, you retry the whole thing. If you need to wait for a human to click "approve," you need to save state somewhere, set up an API Gateway endpoint to receive the callback, wire up the resume logic, and handle the case where your function code changed between the pause and the resume.

Most teams solve this with Step Functions, which works well but means defining your workflow in Amazon States Language (a JSON DSL) or the CDK Step Functions constructs. Your business logic lives in Lambda, your orchestration logic lives in Step Functions, and you context-switch between two mental models.

Lambda Durable Functions puts both in the same file.

How It Works

You enable durable execution when you create the function (a DurableConfig block in your SAM template or CDK construct). Then you use the durable execution SDK in your handler code.

The SDK gives you a few primitives.

  • context.step() runs a block of code and checkpoints the result. If the function fails later and replays, this step is skipped and its cached result is returned.
  • context.wait() suspends execution for a duration (minutes, hours, days). No compute charges during the wait.
  • context.waitForCallback() suspends until an external system calls back with a success or failure. Up to one year.
  • context.waitForCondition() polls a condition on a schedule until it returns true.
  • context.parallel() runs multiple durable operations concurrently.
  • context.invoke() calls another Lambda function and checkpoints the result.

Under the hood, Lambda uses a checkpoint/replay mechanism. When your function resumes (after a wait, a failure, or a deployment), Lambda invokes your handler from the top. The SDK replays through completed steps instantly (returning cached results) and picks up execution at the point where it left off.

checkpoint/replay diagram

What It Looks Like

A user onboarding flow that creates a profile, waits up to 24 hours for email verification, then sends a welcome email.

import { DurableContext, withDurableExecution } from '@aws/durable-execution-sdk-js';

export const handler = withDurableExecution(
  async (event, context: DurableContext) => {
    const profile = await context.step("create-profile", async () =>
      createUserProfile(event.email, event.name)
    );

    const verification = await context.waitForCallback(
      "wait-for-email-verification",
      async (callbackId) => {
        await sendVerificationEmail(profile, callbackId);
      },
      { timeout: { hours: 24 } }
    );

    const result = await context.step("complete-onboarding", async () => {
      if (!verification || !verification.verified) {
        return { ...profile, status: 'failed' };
      }
      await sendWelcomeEmail(profile.email, profile.name);
      return { ...profile, status: 'active' };
    });

    return result;
  }
);

Enter fullscreen mode Exit fullscreen mode

If createUserProfile succeeds but the verification email fails to send, the function retries from the waitForCallback step. The profile creation is skipped (already checkpointed). If the user clicks verify 6 hours later, the function resumes at the complete-onboarding step. During those 6 hours, you pay nothing.

The SAM template looks like this.

Resources:
  UserOnboardingFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: UserOnboardingFunction
      CodeUri: ./src
      Handler: index.handler
      Runtime: nodejs24.x
      Timeout: 60
      DurableConfig:
        ExecutionTimeout: 90000  # 25 hours
        RetentionPeriodInDays: 7

Enter fullscreen mode Exit fullscreen mode

Timeout is still the per-invocation limit (max 15 minutes). ExecutionTimeout is how long the entire durable execution can run, including waits. Up to one year.

When to Use This Instead of Step Functions

The AWS docs frame it as "application development in Lambda" vs. "workflow orchestration across AWS services." Here's my less diplomatic version.

side-by-side comparison, Step Functions state machine vs. durable function code file

Use Durable Functions when

  • Your team prefers standard programming languages and familiar development tools
  • Your workflow is mostly Lambda code calling other services via SDK
  • You want the orchestration logic in the same file as the business logic
  • You're comfortable with the checkpoint/replay model
  • You want to test locally with sam local invoke

Use Step Functions when

  • You're orchestrating many AWS services (SQS, SNS, DynamoDB, ECS) with native integrations
  • Non-engineers need to understand the workflow (the visual designer matters)
  • You want zero runtime maintenance (no SDK versions to update)
  • You need the 220+ direct service integrations without writing Lambda functions for each

Use both when

  • Step Functions coordinates the high-level flow across services
  • Durable Functions handles complex application logic within individual Lambda functions

The honest comparison is that Durable Functions is simpler for Lambda-heavy workflows. Step Functions is more powerful for cross-service orchestration. If your workflow is "Lambda calls Lambda calls Lambda with some waits in between," Durable Functions is less overhead. If your workflow is "receive SQS message, write to DynamoDB, start ECS task, wait for completion, send SNS notification," Step Functions has native integrations for all of that without writing Lambda handlers.

What You Pay For

Standard Lambda compute charges apply to all invocations, including replays. During waits, on-demand functions don't incur duration charges.

You also pay for durable operations (each step(), wait(), invoke() call), data written to checkpoints, and data retention (how long execution history is kept).

For workflows that spend most of their time waiting (approval flows, scheduled delays, polling), the cost model is favorable. You're not paying for an idle Step Functions execution either, but the per-operation pricing differs. For short, compute-heavy workflows with few waits, the replay overhead adds cost that Step Functions doesn't have.

cost timeline showing active compute (colored) vs. suspended wait time (empty)

Things to Know Before You Build

Determinism matters. Your handler runs from the top on every replay. Code between steps must be deterministic. Don't generate random IDs outside a step, don't read the current time outside a step, don't make API calls outside a step. Anything with side effects goes inside context.step().

Versioning is strict. Use function versions or aliases, not $LATEST. If your code changes between a pause and a resume, the replay might not match the original execution. Lambda replays with the version that started the execution.

15-minute invocation limit still applies. Each individual invocation (including replays) must complete within 15 minutes. The durable execution can span months, but each "wake up" is still a normal Lambda invocation. If your replay takes too long because you have hundreds of completed steps to skip through, that's a problem.

You can't add DurableConfig to an existing function. You need to create a new function with durable execution enabled from the start.

SDKs available for Node.js, Python, and Java. Java SDK went GA in April 2026. Python and Node.js have been available since launch.

Available in 16+ regions as of April 2026.

A Practical Example, Order Processing

sequence diagram showing order flow with suspension period marked

Here's a more realistic example. An order comes in, you validate payment, reserve inventory, wait for the warehouse to confirm shipment (could take hours), then notify the customer.

from aws_durable_execution_sdk import durable_function, DurableContext

@durable_function
def handler(event, context: DurableContext):
    order = event

    # Validate payment
    payment = context.step("validate-payment", lambda: charge_card(order))

    if not payment["success"]:
        return {"status": "payment_failed", "order_id": order["id"]}

    # Reserve inventory
    reservation = context.step("reserve-inventory", lambda: reserve_items(order["items"]))

    # Wait for warehouse confirmation (poll every 5 minutes, timeout after 48 hours)
    shipment = context.wait_for_condition(
        "wait-for-shipment",
        check=lambda: check_shipment_status(reservation["id"]),
        interval={"minutes": 5},
        timeout={"hours": 48}
    )

    # Notify customer
    context.step("notify-customer", lambda: send_shipping_notification(
        order["email"], shipment["tracking_number"]
    ))

    return {"status": "shipped", "tracking": shipment["tracking_number"]}

Enter fullscreen mode Exit fullscreen mode

If the warehouse takes 6 hours to ship, the function wakes up every 5 minutes, checks the status, and goes back to sleep. You pay for ~72 invocations of a few hundred milliseconds each, not 6 hours of compute.

Compare this to the Step Functions version. You'd need a state machine with a Wait state, a Choice state, a Lambda function for each step, and the wiring between them. It works, but it's more infrastructure for the same outcome.

Who This Is For

The pattern that makes durable functions worth it is any workflow where you have seconds of actual work separated by hours or days of waiting for something external. The more wait time relative to compute time, the better the cost model.

A few examples that aren't the usual "order processing" and "user onboarding" from the AWS docs.

Trial expiration flow. User signs up for a 14-day trial. The function suspends for 14 days, wakes up, checks if they converted to paid, sends the appropriate email (upgrade nudge or offboarding notice). One function, one execution, two weeks of zero cost. No cron job, no scheduler, no DynamoDB TTL workaround.

export const handler = withDurableExecution(
  async (event, context) => {
    const user = await context.step("create-trial", async () =>
      createTrialAccount(event.email, event.plan)
    );

    await context.wait("trial-period", { days: 14 });

    const converted = await context.step("check-conversion", async () =>
      hasUpgradedToPaid(user.id)
    );

    await context.step("send-email", async () => {
      if (converted) return sendRetentionEmail(user.email);
      return sendOffboardingEmail(user.email);
    });

    if (!converted) {
      await context.step("deactivate", async () => deactivateAccount(user.id));
    }

    return { userId: user.id, converted };
  }
);

Enter fullscreen mode Exit fullscreen mode

Webhook delivery with backoff. First attempt fails. Wait 1 minute, retry. Wait 5 minutes, retry. Wait 30 minutes, retry. The waits cost nothing.

export const handler = withDurableExecution(
  async (event, context) => {
    const { url, payload, maxAttempts = 4 } = event;
    const delays = [0, 1, 5, 30]; // minutes

    for (let attempt = 0; attempt < maxAttempts; attempt++) {
      if (delays[attempt] > 0) {
        await context.wait(`backoff-${attempt}`, { minutes: delays[attempt] });
      }

      const result = await context.step(`deliver-${attempt}`, async () =>
        deliverWebhook(url, payload)
      );

      if (result.success) return { delivered: true, attempts: attempt + 1 };
    }

    await context.step("mark-failed", async () =>
      markWebhookFailed(event.webhookId)
    );

    return { delivered: false, attempts: maxAttempts };
  }
);

Enter fullscreen mode Exit fullscreen mode

Infrastructure provisioning with approval gates. Terraform plan runs, posts to Slack, suspends until someone approves.

export const handler = withDurableExecution(
  async (event, context) => {
    const plan = await context.step("terraform-plan", async () =>
      runTerraformPlan(event.workspace)
    );

    if (plan.changes === 0) return { status: "no_changes" };

    const approval = await context.waitForCallback(
      "wait-for-approval",
      async (callbackId) => {
        await postToSlack(event.channel, {
          text: `Terraform wants to change ${plan.changes} resources in ${event.workspace}`,
          planUrl: plan.outputUrl,
          approveUrl: buildApproveUrl(callbackId),
          rejectUrl: buildRejectUrl(callbackId)
        });
      },
      { timeout: { hours: 24 } }
    );

    if (!approval || !approval.approved) {
      return { status: "rejected", by: approval?.user };
    }

    const apply = await context.step("terraform-apply", async () =>
      runTerraformApply(event.workspace)
    );

    return { status: "applied", resources: apply.changed };
  }
);

Enter fullscreen mode Exit fullscreen mode

Incident response with human escalation. Auto-isolate, alert, wait for analyst confirmation.

export const handler = withDurableExecution(
  async (event, context) => {
    const finding = event.detail;

    const isolation = await context.step("isolate-instance", async () =>
      isolateEc2Instance(finding.instanceId)
    );

    const decision = await context.waitForCallback(
      "wait-for-analyst",
      async (callbackId) => {
        await createPagerDutyIncident({
          title: `Isolated ${finding.instanceId} - ${finding.type}`,
          details: finding,
          callbackId
        });
      },
      { timeout: { hours: 4 } }
    );

    if (!decision || decision.action === "terminate") {
      await context.step("terminate", async () =>
        terminateInstance(finding.instanceId)
      );
      return { outcome: "terminated" };
    }

    await context.step("restore", async () =>
      restoreInstance(finding.instanceId, isolation.previousSecurityGroups)
    );

    return { outcome: "restored" };
  }
);

Enter fullscreen mode Exit fullscreen mode

Scheduled certificate rotation. Check, renew, wait for DNS validation, swap.

export const handler = withDurableExecution(
  async (event, context) => {
    const cert = await context.step("check-expiry", async () =>
      getCertificateDetails(event.certArn)
    );

    if (cert.daysUntilExpiry > 30) return { status: "not_due" };

    const renewal = await context.step("request-renewal", async () =>
      requestCertificate(cert.domain)
    );

    const validated = await context.waitForCondition(
      "wait-for-validation",
      async () => checkValidationStatus(renewal.arn) === "ISSUED",
      { interval: { minutes: 2 }, timeout: { minutes: 30 } }
    );

    if (!validated) return { status: "validation_failed" };

    await context.step("swap-cert", async () =>
      updateListenerCertificate(event.listenerArn, renewal.arn)
    );

    return { status: "rotated", newCertArn: renewal.arn };
  }
);

Enter fullscreen mode Exit fullscreen mode

The common thread is that these workflows are too simple for Step Functions (5-7 steps, mostly Lambda code) but too stateful for a single Lambda invocation. That's the gap durable functions fill.


Getting Started

sam init  # Choose the durable functions quick start template
sam local invoke  # Test locally, including callbacks
sam deploy  # Ship it

Enter fullscreen mode Exit fullscreen mode

The developer guide covers setup. The re:Invent breakout session is worth watching for the architecture deep dive.

Lambda Durable Functions | Documentation | Pricing