OpenWorkflow is a TypeScript framework for building durable, resumable workflows that can pause for seconds or months, survive crashes and deploys, and resume exactly where they left off - all without extra servers to manage.
import { defineWorkflow } from "openworkflow";
export const sendWelcomeEmail = defineWorkflow(
{ name: "send-welcome-email" },
async ({ input, step }) => {
const user = await step.run({ name: "fetch-user" }, async () => {
return await db.users.findOne({ id: input.userId });
});
await step.run({ name: "send-email" }, async () => {
return await resend.emails.send({
from: "me@example.com",
to: user.email,
replyTo: "me@example.com",
subject: "Welcome!",
html: "<h1>Welcome to our app!</h1>",
});
});
await step.run({ name: "mark-welcome-email-sent" }, async () => {
await db.users.update(input.userId, { welcomeEmailSent: true });
});
return { user };
},
);Prerequisites: Node.js & PostgreSQL (or SQLite)
npx @openworkflow/cli initThe CLI will guide you through setup and generate everything you need to get started.
For more details, check out our docs.
- ✅ Durable - Workflows survive crashes and deploys
- ✅ Resumable - Pick up exactly where you left off
- ✅ Type-safe - Full TypeScript support
- ✅ Step memoization - Never repeat completed work
- ✅ Automatic retries - Built-in exponential backoff
- ✅ Long pauses - Sleep for seconds or months
- ✅ Parallel execution - Run steps concurrently
- ✅ No extra servers - Uses your existing database
- ✅ Dashboard included - Monitor and debug workflows
- ✅ Production ready - PostgreSQL and SQLite support
Read ARCHITECTURE.md for a deep dive into how OpenWorkflow works under the hood.
Check out examples/ for working examples.
We welcome contributions! Please read CONTRIBUTING.md before submitting a pull request.
- GitHub Issues - Report bugs and request features
- Roadmap - See what's coming next