Flue Zero to Expert, Part 5: Persistence and Durable Execution
Persist Flue state with SQLite or Postgres, understand recovery limits, and make external effects idempotent.
Series map
Part 1: Your First Flue Agent · Part 2: Typed Workflows · Part 3: Safe Tools · Part 4: Autonomous Agents · Part 5: Persistence and Durable Execution · Part 6: Production Routing and Deployment · Part 7: Operate Like an Expert
Part 5: Persistence and Durable Execution
Persistence starts in memory
On Node.js, Flue uses in-memory SQLite by default.
This stores agent conversations, accepted submissions, and workflow records while the process runs. Everything disappears when the process exits.
That default is useful for experiments. It is unsafe when accepted work must survive a restart.
Flue discovers persistence through a source-root db.ts. In a standard project, create src/db.ts.
Complete example: durable Node storage
For a single-host service, use file-backed SQLite:
// src/db.ts
import { sqlite } from '@flue/runtime/node';
export default sqlite('./data/flue.db');Flue finds this file at build time. The generated Node server wires the exported adapter into the runtime.
The database survives process restarts on the same host. It does not survive losing that host. It also cannot be shared safely by several replicas.
For storage outside the application host, use Postgres:
// src/db.ts
import { postgres } from '@flue/postgres';
export default postgres(process.env.DATABASE_URL!);The Postgres adapter runs its migrate() hook when the generated Node server starts.
Postgres is the better choice when a replacement process must recover accepted work after host loss. It also lets several replicas inspect shared workflow history.
Shared storage does not provide shared execution ownership.
What Flue stores
The adapter stores Flue runtime state:
- Canonical agent conversation streams.
- Immutable attachment payloads.
- Accepted direct prompts.
- Accepted
dispatch(...)submissions. - Workflow-run records.
- Workflow event streams.
- Run indexes used by
/runsandlistRuns().
The canonical conversation stream is the source of truth. Flue replays it from the beginning to rebuild an agent’s context.
Flue does not store your whole application.
It does not persist sandbox files, installed dependencies, provider secrets, or external API effects. It also does not replace your business database.
A persisted conversation does not make a sandbox durable. A durable workspace does not preserve conversation history. Configure those concerns separately.
Agent recovery is not workflow retry
Agents are continuing contexts. Each persistent agent instance owns one canonical conversation stream.
After an interruption, Flue reads that stream and recovers conservatively. It can reuse completed tool results and durable partial output. If a tool call may have started but has no durable result, Flue marks its outcome as unknown. It does not automatically repeat the call.
When no output was persisted, provider execution may occur again. Treat agent recovery as at-least-once execution.
Workflows are different. A workflow is a finite call to run(...) with its own runId.
Flue does not checkpoint arbitrary TypeScript and resume at the last completed line. Retrying a workflow starts a new invocation. Your application must decide whether that is safe.
On Node.js, durable storage preserves an interrupted workflow’s record and events. It does not resume or finish the run. The run can remain active, and live readers can wait indefinitely.
Use recorded events to inspect what happened. Start a new workflow only when your application’s retry policy permits it.
Make external effects idempotent
Persistence cannot prove whether an interrupted external request succeeded.
Suppose an agent creates a support ticket. The remote service may create the ticket just before the Node process dies. Recovery sees no durable tool result, so the outcome is unknown.
Send an application-owned idempotency key with the request. Store that key with the ticket in your business system. Enforce uniqueness there.
Use the same rule for payments, emails, job creation, and webhook handling. The database can preserve Flue’s records, but it cannot undo or deduplicate effects in another system.
Keep one Node owner per agent instance
Node requires one live process to own a given agent instance.
Postgres supports replacement recovery and shared history. It does not make active-active execution safe. Do not round-robin requests for one instance across replicas.
Route each agent instance to one live owner. During replacement, avoid overlapping old and new owners.
File-backed SQLite fits one host. Postgres fits host replacement and shared inspection. Neither removes the single-owner limit.
Sources
Next, continue to Part 6: Production Routing and Deployment to protect and deploy the service.