Targets Database

Purpose and Scope

This page explains how database configuration fits into a Node-target Flue application. In Flue, the database is not an optional logging sink; it is part of the durable harness that preserves agent conversations, accepted submissions, workflow run records, and event history across runtime boundaries. The Node target builds a normal server process, so persistence must be selected explicitly when state needs to outlive a process. That makes the database decision part of application architecture rather than a deployment afterthought: it affects restart recovery, host replacement, routing, and how safely a running agent instance can be owned.

Sources: apps/docs/src/content/docs/guide/targets/node.md

The most important distinction is between process-local state and durable state. Without a project-level database adapter, the Node server uses in-memory SQLite for its canonical state. That still gives one running process ordered handling of agent and workflow activity, but all state disappears when the process exits. With a durable adapter, direct prompts and programmatic dispatch inputs enter a persisted per-instance queue. A replacement process can recover canonical conversation progress and interrupted agent submissions because the accepted work is recorded outside the original process.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Database configuration is Node-specific in the Flue docs. Cloudflare builds use Durable Objects with SQLite storage automatically, while Node applications use a source-root db.ts file when they want persistence beyond a single process. The generated Node server is also the target where agents can use the host filesystem and shell through local sandbox support, so Node deployments often combine durable state with host-aware automation. Treat the database as the durable coordination layer for accepted work, not as a mechanism that magically makes every Node process active-active.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Relevant Source Files

  • apps/docs/src/content/docs/guide/targets/node.md — Documents the Node target, generated server entry, runtime ports, dependency externalization, in-memory default state, durable adapter behavior, ownership constraints, lease reconciliation, and Node-specific recovery limitations.

How db.ts Is Discovered and Wired

For Node applications, database setup is expressed through a source-root db.ts file. The expected shape is a default export that provides a PersistenceAdapter. At build time, Flue discovers that file and wires the exported adapter into the generated Node server entry. A minimal SQLite-backed configuration looks like this:

db.ts
import { sqlite } from '@flue/runtime/node';
 
export default sqlite('./data/flue.db');

The file path matters because Flue discovery happens from the project source root, alongside the source directories used for agents and workflows. The Node guide says agents are discovered from src/agents/ and workflows from src/workflows/, then Flue generates a single server entry at dist/server.mjs. Database discovery follows the same build-time model: the application source describes durable resources, and the generated server composes them into one runtime entrypoint. If db.ts is not present, the generated server still has a database-like state layer, but it is the process-local in-memory SQLite default.

Sources: apps/docs/src/content/docs/guide/targets/node.md

The adapter provides the stores Flue needs for canonical agent execution. The official Database guide describes this as the append-only conversation stream for each agent instance, immutable attachment payloads referenced by conversation records, accepted direct prompts, dispatch submissions, workflow-run records, workflow event streams, and run indexing for lookup APIs. That list is useful when evaluating adapters because it shows that Flue needs more than a key-value cache. The persistence layer must support ordered state, immutable payload references, durable submissions, and queryable workflow metadata used by runtime and client APIs.

Node Target Runtime Flow

A Node-target build produces a standard Node.js server that can run anywhere Node runs: a local machine, container, virtual machine, CI runner, or managed hosting service. The generated server owns HTTP routes, agent dispatch, workflow admission, and event streaming routes. Build and start the generated server with the documented command sequence:

npx flue build --target node
node dist/server.mjs

By default, the server listens on port 3000, while flue dev --target node uses port 3583 and reloads on changes. The build externalizes application dependencies instead of bundling them, so a deployment must ship the built artifact with its node_modules or run inside an environment that installs dependencies first. That packaging detail is database-relevant because adapters such as SQLite, Postgres, or custom drivers are application dependencies. If the generated server can import the application code but not the adapter package or native driver it depends on, startup will fail before persistence can be initialized.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Once the server starts, prompts and dispatch calls are admitted through the same runtime ownership model. With a durable adapter, inputs for one agent instance enter a persisted queue and are processed in accepted order. This is the behavior readers usually want from a database-backed Flue deployment: a task accepted before a restart remains part of the canonical history, and a replacement process has enough durable information to continue agent progress. The database preserves accepted work and conversation state; the runtime process still performs execution, model calls, tool invocation, and stream delivery.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Persistence Choices and Deployment Meaning

The built-in Node SQLite adapter is the simplest durable option. Passing a file path creates state that survives process restart on the same host, while omitting the path creates an in-memory database equivalent to not adding db.ts. File-backed SQLite is well suited to local development, single-host services, small internal deployments, and agents whose durable state can safely live on one machine. It is not a host-replacement strategy by itself because the file belongs to the machine or mounted volume that stores it.

A networked durable adapter, such as a Postgres-style deployment described by the official docs, changes the failure boundary. It can preserve state when a process or host is replaced because the canonical records live in a database independent of one Node process. That does not mean multiple replicas can all actively own the same agent instance. The Node guide is explicit that one live process must own a given agent instance. A shared database supports replacement, but it does not make active-active ownership or round-robin routing safe for the same instance.

Sources: apps/docs/src/content/docs/guide/targets/node.md

For multi-replica Node deployments, route each agent instance to one owner and avoid overlapping owners during replacement. The database gives the new owner durable records to resume from, but it is not a distributed lock manager that automatically coordinates every HTTP load balancer decision. If two processes accept and execute work for the same instance at the same time, they can violate the runtime’s ownership assumptions even if they share the same backing store. In practice, pair durable persistence with sticky routing, instance-aware scheduling, or an external ownership layer appropriate to your hosting platform.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Recovery Semantics and Limits

Durable state improves restart behavior, but Node recovery is intentionally different from Cloudflare Durable Object recovery. The Node guide notes that Node does not get Cloudflare’s automatic Durable Object wake or Fiber recovery. A replacement process must start successfully before startup reconciliation can run. The coordinator also periodically scans expired leases so work stranded by a fast restart is eventually reclaimed. This means a database-backed Node service should be monitored like any other long-running server: the process must come back, imports must resolve, environment variables must be present, and the adapter must connect.

Sources: apps/docs/src/content/docs/guide/targets/node.md

The current reconciliation behavior is also scoped. It covers agent submissions, but the Node guide calls out a workflow limitation: Node currently has no recovery path that terminalizes a workflow run interrupted by a crash or closes its event stream. With a durable adapter, the run record and events already written before the crash survive, but the interrupted run can remain listed as active and its stream can remain open. Live stream readers such as long-polling clients, SSE clients, or client.runs.stream() can wait indefinitely for events that will never arrive.

Sources: apps/docs/src/content/docs/guide/targets/node.md

That limitation affects how you operate and debug database-backed Node applications. For interrupted workflow runs, inspect persisted events with catch-up reads such as client.runs.events() or an equivalent raw event read instead of assuming a live stream will complete. For agent submissions, expect the lease reconciliation path to reclaim stranded accepted work after the replacement process is healthy. In both cases, the database preserves evidence of what happened, but it does not replace operational readiness, application-level idempotency, or a deployment strategy that avoids unnecessary overlapping owners.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Configuration Reference

Use this compact checklist when deciding how to configure persistence for a Node target application:

ConcernNode target behaviorPractical choice
No db.tsProcess-local in-memory SQLiteUseful for throwaway development or tests where restart persistence is not needed
db.ts with sqlite('./data/flue.db')File-backed SQLite adapterGood for local development and single-host deployments
Networked durable adapterShared database-backed PersistenceAdapterSupports process or host replacement, but still requires single active owner per agent instance
Cloudflare targetDoes not use db.tsDurable Objects store canonical state automatically
Workflow crash recovery on NodePersisted records survive, but interrupted workflow streams may stay openInspect persisted events and design operational cleanup accordingly

A database-backed Node Flue application should therefore be designed around three decisions. First, choose the adapter that matches your failure boundary: in-memory for ephemeral runs, file SQLite for single-host durability, or a shared adapter for host replacement. Second, deploy the generated dist/server.mjs with all application dependencies needed by the adapter. Third, preserve the single-owner rule for each agent instance, because durability supports recovery and continuity but does not authorize multiple Node processes to execute the same instance concurrently.

Sources: apps/docs/src/content/docs/guide/targets/node.md

Next Steps

After adding db.ts, run a Node build and start the generated server to confirm the adapter loads in the same environment you plan to deploy. Exercise one direct prompt or dispatch call, restart the server, and verify the conversation or accepted submission still appears in the canonical state. If you are preparing a multi-replica deployment, document how requests for a given agent instance are routed to one owner and how replacement avoids overlap. For deeper API-level work, read the Data Persistence API next; for behavior during failures, read Durable Execution and the Node target guide together.