Chapter 15 · Deployment: Node.js and Cloudflare Workers
Chapter goals: Deploy Flue agents to two official targets — long-lived Node.js services and Cloudflare Workers edge runtime — and understand the persistence and credential management differences.
15.1 Common Prerequisites for Both Targets
Regardless of where you deploy, three things must be solved first:
① Build artifact (@flue/vite handles agent code packaging)
② Provider credential injection (env vars / Secrets)
③ Persistent storage (where Durability state lives)// vite.config.ts — build config entry for both targets
import { flue } from '@flue/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [flue()], // Handles 'use agent' directives and runtime packaging
});15.2 Node.js Deployment
Node is the most straightforward long-running target: the process stays alive, recovery happens自动 on startup.
// src/main.ts — production entry
import { createApp } from '@flue/runtime/node';
import { postgresAdapter } from '@flue/postgres';
import { Pool } from 'pg';
const app = createApp({
// Production requires external persistence; only then can in-progress sessions recover on restart
database: postgresAdapter({
pool: new Pool({ connectionString: process.env.DATABASE_URL }),
}),
});
app.listen(process.env.PORT ?? 3000);# Build and run
npm run build # vite build
NODE_ENV=production node dist/main.js
# Daemon with PM2 (or systemd / Docker)
pm2 start dist/main.js --name flue-bot# Dockerfile — containerized Node deployment
FROM node:22-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY dist ./dist
# Keys injected via env vars; never baked into the image
ENV NODE_ENV=production
CMD ["node", "dist/main.js"]15.3 Cloudflare Workers Deployment
Workers are serverless isolates: no long-lived process, woken by requests and cron alarms; persistence natively goes through the database.
// src/worker.ts — Workers entry
import { createWorkerApp } from '@flue/runtime/cloudflare';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Get bindings from env: database (D1/Hyperdrive) and Secrets
const app = createWorkerApp({ env });
return app.fetch(request);
},
// Cron alarm: periodically advance unfinished admissions (see Chapter 12 recovery behavior)
async scheduled(_ctrl: ScheduledController, env: Env) {
const app = createWorkerApp({ env });
await app.resumePending();
},
};# wrangler.toml — Workers config
name = "flue-agent"
main = "src/worker.ts"
compatibility_date = "2026-01-01"
[triggers]
crons = ["*/5 * * * *"] # Wake every 5 minutes for recovery checksnpx wrangler deploy15.4 Credentials and Environment Variables
The injection mechanism differs per target, but the reading pattern is统一:
| Target | Local Dev | Production Injection |
|---|---|---|
| Node.js | .env file | System env vars / Docker ENV / K8s Secret |
| Workers | .dev.vars file | wrangler secret put XXX |
# Workers credential injection (interactive, never written to disk)
npx wrangler secret put ANTHROPIC_API_KEY
npx wrangler secret put DATABASE_URL// Unified reading: code is unaware of the deployment target difference
// Node: process.env.XXX; Workers: env.XXX (normalized by the adapter)
const apiKey = env.ANTHROPIC_API_KEY ?? process.env.ANTHROPIC_API_KEY;
if (!apiKey) throw new Error('missing ANTHROPIC_API_KEY');The essential difference between the two targets
Node: process stays alive → recovery triggered by restart; Workers: isolate reclaimed at any time → recovery triggered by next request or cron alarm. Business code hardly changes, but the运维 mental model differs.
15.5 Chapter Summary
- Common prerequisites:
@flue/vitebuild, credential injection, external persistence; - Node long-lived:
postgresAdapter+ PM2/Docker daemon; recovery on restart; - Workers serverless:
createWorkerApp({ env })+ cron alarm for recovery checks; - Credentials: local
.env/.dev.vars; production system env vars orwrangler secret put.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. How does recovery触发 differ between Node.js and Cloudflare Workers?
2. What is the correct way to manage生产 keys on Cloudflare Workers?
3. Why does the Workers config need a cron trigger?
4. What is the common prerequisite for both deployment targets?
🛠️ Hands-On Exercises
- Deploy the Chapter 11 Triage agent as a Node service;守护 with PM2 and verify auto-recovery after kill.
- Deploy the same agent to Cloudflare Workers; configure a 5-minute cron; observe the wake logs in the Dashboard.
- Inject credentials using both
.envandwrangler secret put; write a team credential management清单.
Deployment mastered. Next, CI/CD Integration.