Answers you can trust, from Codeables

Every page on Codeables is structured and verified — built so people and the AI agents they rely on can trust it. Explore more from the source behind this answer.

Explore Codeables
Verified Source
Platform as a Service (PaaS)

We deployed our AI assistant on serverless (Lambda/Workers) and it forgets everything between requests—how do people add durable agent state without building a whole state service?

LiquidMetal AI10 min read

Most teams hit the same wall you’re describing: the “it forgets everything between requests” problem is not a bug in your Lambda or Worker—it’s the core design of stateless serverless. Every invocation is a fresh process. No memory, no session, no conversation history unless you bolt it on.

Quick Answer: You make your AI assistant stateful by moving the memory out of functions and into a durable state layer—typically a combination of storage + identity routing + some form of “actor” or session abstraction. You can roll your own with DynamoDB/Redis/Postgres plus glue code, use stateful runtimes like Durable Objects/Actors, or adopt an AI-native runtime like Raindrop that treats SmartMemory as a built-in primitive instead of a separate “state service” you have to engineer from scratch.

Why This Matters

If your assistant can’t remember prior turns, cart state, or a user’s preferences, it never escapes “demo mode.” Stateless functions are great for bursts of compute, but they’re hostile to agent workflows that span multiple steps, tools, or conversations.

Durable agent state is what turns a one-off completion into a product:

  • An onboarding copilot that remembers what a customer already configured.
  • A support agent that knows past tickets and decisions.
  • A research assistant that builds on previous documents instead of re-ingesting them every time.

If you solve state by duct-taping databases, caches, and ad-hoc session handling, you inherit a long-tail of complexity: race conditions, partial writes, migrations, and debugging across five different dashboards. The goal is durable state without building a bespoke “state service” just to keep your assistant coherent.

Key Benefits:

  • Coherent multi-turn behavior: Conversation history, reasoning chains, and tool outputs persist across invocations, so your assistant behaves like a continuous agent instead of a stateless function.
  • Less glue work, fewer systems: A dedicated state abstraction (Actors, SmartMemory) avoids stitching together Redis, SQL, vector DBs, and ad-hoc session tables for every new agent workflow.
  • Production safety from day one: When state is a first-class primitive with versioning, observability, and isolation, you can experiment and roll back without corrupting user data.

Core Concepts & Key Points

ConceptDefinitionWhy it's important
Stateless serverlessFunctions (Lambda, Workers, Functions) that spin up on demand, handle a single request, and then disappear with no persistent memoryPerfect for short-lived compute, but every AI interaction starts from zero context unless you externalize state
Durable agent stateThe persisted memory of an agent: conversation turns, plans, tool results, user profile, and long-running workflowsEnables coherent agents that can continue tasks, remember preferences, and coordinate across multiple calls
Stateful runtimes & memory primitivesPlatforms or abstractions (Actors, Durable Objects, SmartMemory) that keep data and compute logically bound to an identity and persist across requestsRemove the need to hand-roll a state service, with built-in routing, consistency, and observability for agent workloads

How It Works (Step-by-Step)

At a high level, every durable agent architecture does the same three things:

  1. Attach requests to an identity
  2. Load state for that identity
  3. Update and persist state after each step

The difference between “glue hell” and “productive” is how much of this you have to implement yourself.

1. Identity: Decide who the state belongs to

You need a stable key to bind state:

  • user_id (authenticated user)
  • session_id (ephemeral chat session or cart)
  • agent_id (long-running worker, team, or bot)

On raw Lambda/Workers:

  • You typically derive this from JWT, cookies, or a URL parameter.
  • You manually pass it around across all functions and queues.

On stateful platforms / AI runtimes:

  • The identity is part of the abstraction:
    • Cloudflare Durable Objects: one object per ID.
    • Actor model (like Raindrop Actors): one actor per user/session, with routing built in.
    • SmartMemory sessions: one memory namespace per identity.

2. Rehydrate: Load the agent’s memory at the start of each call

Once you know the identity, you need to rehydrate context:

DIY pattern on Lambda/Workers:

  • Read from:
    • A session table in Postgres/DynamoDB
    • A Redis cache for hot conversations
    • A vector DB / embeddings store for semantic context
  • Compose:
    • Conversation history (truncated)
    • Relevant documents via RAG
    • User profile / preferences

This works, but every new feature adds more joins, more cache invalidation, and more RAG plumbing.

AI-native pattern with built-ins:

  • Use a memory primitive that handles rehydration:
    • SmartMemory (Raindrop): working/episodic + semantic/procedural memory are automatically loaded per session/actor.
    • Durable runtime: the object/actor already holds state in memory between invocations and persists to storage under the hood.

Your assistant invocation code becomes:

  • “Load memory for session_id
  • “Ask the model with current state”
  • “Write back new memory”

Instead of “join six tables and manually hydrate context every single time.”

3. Persist: Save new state reliably and traceably

After the model runs and tools execute:

  • Append the latest messages to conversation history
  • Update any plans, tasks, or loops
  • Store new knowledge (e.g., documents uploaded, preferences set)

On raw serverless:

  • You write to your own storage (SQL/NoSQL/cache/vector DB)
  • Ensure idempotency, handle partial failures, and lock contention
  • Implement retention, cleanup jobs, and schema migrations yourself

On AI-native runtimes:

  • Writes go through a versioned, observable memory primitive:
    • In Raindrop, SmartMemory updates are automatically logged and versioned alongside compute.
    • Rollback/rollforward lets you revert a bad memory change across code + data.
    • Full traces show “which prompt/tool write produced this memory update.”

This is the difference between “our logs say something weird happened” and “we can see the exact AI decision that corrupted this state and roll back safely.”


The three main paths people take

In practice, teams gravitate to one of three patterns:

  1. DIY state service on top of Lambda/Workers
  2. Stateful serverless runtimes (Durable Objects/Actors)
  3. AI-native runtimes with built-in SmartMemory (e.g., Raindrop)

Let’s walk each with concrete details.

Path 1: DIY state on top of Lambda/Workers

What it looks like:

  • Stateless function per request.
  • Storage layer:
    • Conversation state in DynamoDB/Postgres
    • Ephemeral cache in Redis
    • Vector DB (Pinecone, pgvector, etc.) for RAG
  • A “SessionManager” or “StateService” module that:
    • Reads/writes per user_id or session_id
    • Handles TTLs and cleanup
    • Manages migrations & schema evolution

Pros:

  • Uses infra you already have (AWS, GCP, Cloudflare)
  • Full control over schema, indexes, and retention
  • Works with existing observability and compliance setup

Cons:

  • You are building a state service:
    • Race conditions across multiple Lambdas updating the same session
    • Complex retries and idempotency logic
    • Custom tools for debugging and inspecting agent state
  • RAG and memory are bolted on, not integrated:
    • One pipeline for relational data, one for semantic, one for logs

This approach is fine if you’re already heavily invested in AWS/GCP and have strong infra/devops. But your AI team is now an infrastructure team.

Path 2: Stateful runtimes (Durable Objects / Actors)

What it looks like:

  • You move from purely stateless functions to stateful compute units:
    • Cloudflare Durable Objects
    • Azure Durable Functions
    • Actor frameworks, etc.
  • Each user/session maps to a specific object/actor.
  • That object holds state in memory and persists it between calls.

Pros:

  • Fixes “functions forget everything between requests”
  • Identity routing is built in: all requests for a session hit the same object
  • Simplifies concurrent updates: single-threaded per actor/object

Cons:

  • Still need to integrate:
    • Authentication/authorization
    • Billing/usage tracking
    • RAG stack (vector DB, embeddings, doc pipelines)
  • Vendor-specific programming model; migration is non-trivial
  • You still assemble AI pieces (models, memory, storage) manually

This is a big step up from pure Lambda/Workers if you want durable state, but it doesn’t eliminate the rest of the glue.

Path 3: AI-native runtime with SmartMemory (Raindrop)

This is the path we built Raindrop for, after doing the first two in production one too many times.

What it looks like:

  • You define your assistant as an API in a manifest (Developer Mode) or describe what you need (AI Mode).
  • Raindrop:
    • Builds, tests, and deploys a complete API.
    • Wires in SmartMemory as the durable agent state layer.
    • Provides SmartBuckets, SmartSQL, and SmartInference for storage, analytics, and models.
  • You get Actors for stateful compute:
    • One actor per user/session/agent with persistent state.
    • Identity routing handled by the platform.
    • Built-in scheduling/alarms for long-running work.

Pros:

  • Intelligence is built in, not bolted on:
    • SmartMemory: working/episodic + semantic/procedural memory, session rehydration.
    • SmartBuckets: S3-compatible storage with automatic embeddings and semantic/graph search.
    • SmartSQL: natural language to SQL with automatic PII detection.
    • SmartInference: single interface for 60+ models with auto-scaling.
  • Production-ready from day one:
    • Complete Versioning: code, data, and smart primitives versioned together with instant rollback/rollforward.
    • Full Observability: every AI decision and memory operation logged and traceable.
    • Built-in Authentication (JWT, OAuth, RBAC) and Monetization (plans, usage, payments).
  • Automatic scaling without configuration: you don’t tune concurrency for your agents or memory.

Cons:

  • It’s a new runtime, not just “add one more library” to an existing Lambda stack.
  • Best when you’re ready to treat the assistant as a product, not just an endpoint attached to a monolith.

If your main blocker today is “we don’t want to build a state service,” this path gives you durable agent state as a primitive instead of a project.

Common Mistakes to Avoid

  • Treating every request as stateless forever:
    Trying to cram conversation history into a single payload (JWT, cookies) or re-sending full history on every call will hit size/latency limits. Instead, centralize memory in durable storage or a dedicated memory primitive and rehydrate selectively.

  • Mixing transient compute with long-term memory blindly:
    Writing every intermediate tool output to the same table or vector index as long-lived knowledge makes cleanup and compliance impossible. Separate:

    • Working memory (per session, short-lived)
    • Episodic memory (per user, medium-lived)
    • Semantic/procedural memory (documents, skills, institutional knowledge)
      SmartMemory in Raindrop models this separation explicitly so you don’t have to invent it.

Real-World Example

A team I worked with deployed a support copilot as an AWS Lambda + API Gateway endpoint. First version was simple:

  • Lambda calls an LLM with the last 10 messages in the body.
  • No persistent memory; the frontend kept local history.

Users loved the first impression but quickly hit pain:

  • Switching devices lost the entire conversation context.
  • Long-running investigations (multi-day issues) forced agents to re-explain everything.
  • Adding “customer profile” context meant yet another database lookup per call.

They considered building:

  • A session table in DynamoDB for chat logs
  • A nightly job to prune old conversations
  • A separate RAG pipeline for historical tickets and docs
  • A custom dashboard to debug “what did the agent know when it answered?”

Instead, they moved the assistant into Raindrop:

  • Defined the copilot API in a manifest.
  • Used SmartMemory to:
    • Maintain working/episodic memory per customer and per ticket.
    • Persist conversation history and decisions.
    • Automatically rehydrate context, so Lambda-style “stateless” invocations were no longer a constraint.
  • Stored knowledge base docs and past tickets in SmartBuckets, getting:
    • Automatic embeddings
    • Semantic and graph search out of the box
  • Exposed the API with built-in Authentication and turned on Monetization for partner access.

Result:

  • Durable agent state without building a state service.
  • Clear lineage: they could inspect the memory state and AI decisions for any response.
  • Safe iteration: when they changed prompt strategies, they used Raindrop’s complete versioning to roll forward and back both code and memory schema, without losing user data.

Pro Tip: Even if you stay on Lambda/Workers today, design your assistant around an identity + memory abstraction (e.g., MemoryStore.load(userId) / MemoryStore.save(session)). It makes the migration to stateful runtimes or SmartMemory trivial later—you swap implementation, not your entire app.

Summary

Serverless functions forgetting everything between requests isn’t something you “fix” in Lambda or Workers—it’s how they’re built. Durable agent state comes from attaching requests to an identity, rehydrating memory at each step, and persisting updates in a dedicated state layer.

You can:

  • Assemble your own state service on top of Lambda/Workers (DBs + caches + vector stores).
  • Move to stateful runtimes like Durable Objects or Actors that bake in identity routing and persistence.
  • Use an AI-native runtime like Raindrop, where SmartMemory, SmartBuckets, SmartSQL, and SmartInference give you durable agent state, RAG, and observability as built-in primitives.

If your goal is a production assistant—not just a demo endpoint—investing in a proper state layer early will save you months of glue work and painful debugging later.

Next Step

Get Started