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
Tested with@flue/runtimeand@flue/postgres1.0.0-beta.9 on Node.js.
Persistence starts in memory
On Node.js, Flue uses in-memory SQLite by default. It stores agent conversations, accepted submissions, and workflow records only while the process runs.
Flue discovers persistence through a source-root db.ts, normally src/db.ts. For a single-host service, use file-backed SQLite:
// src/db.ts
import { sqlite } from '@flue/runtime/node';
export default sqlite('./data/flue.db');This survives process restarts, but not loss of the host, and it is not shared storage for several replicas.
For Postgres, use the official blueprint:
npx flue add database postgresThe blueprint installs @flue/postgres, lets you choose a driver, and writes the driver-backed db.ts. In beta.9, postgres(...) accepts a PostgresRunner with query, transaction, and close; it does not accept a connection string. The package README includes complete pg and postgres driver examples. Flue runs the adapter's idempotent migrate() hook at startup.
Postgres is useful when state must survive host replacement or several replicas need shared workflow history. Shared storage still does not provide shared execution ownership: keep one live Node owner for each agent instance and avoid overlap during replacement.
The Cloudflare target is different. Its generated Durable Objects use SQLite automatically and reject db.ts.
What Flue stores
The adapter stores Flue runtime state:
- The append-only conversation history for each agent instance.
- Immutable attachment payloads.
- Accepted direct prompts and
dispatch(...)submissions. - Workflow-run records, event streams, and run indexes used by
/runsandlistRuns().
It does not persist sandbox files, installed dependencies, provider secrets, external API effects, or your application records. Keep business data in your business database and configure durable workspaces separately when needed.
Recovery is conservative
Flue reuses completed tool results and durable partial output. If a tool may have started but has no durable result, its outcome is unknown and Flue does not automatically repeat it. Provider execution may happen again only when no output was durably persisted.
Workflows are finite calls to run(...) with a runId. Flue does not checkpoint arbitrary TypeScript and resume from the last line. After an interruption, a Node workflow record can remain active, and a live reader can wait indefinitely. Inspect its recorded events, then start a new invocation only when your retry policy permits it.
Make external effects idempotent
Persistence cannot prove whether an interrupted external request succeeded. Send an application-owned idempotency key for payments, emails, tickets, jobs, and webhooks, store it with the effect, and enforce uniqueness in the system that owns that effect.
Sources
Next, continue to Part 6: Production Routing and Deployment.