Skip to main content

Building Stateful Workflows in JavaScript: A Guide to Codehooks Workflow API

· 4 min read
Jones
Co-Founder and Architect @ Codehooks

At Codehooks, our mission is to simplify the development of automations, integrations, and backend APIs. As your app logic grows more complex — onboarding flows, async jobs, conditional steps — it becomes clear: You need a better way to organize and execute business logic.

That's why we built the Codehooks Workflow API — a lightweight, serverless-friendly way to run stateful workflows in JavaScript, without the overhead of bulky orchestrators or external tools.

socialcard

✨ Why Workflows Matter

  • Step-by-step Logic: Break down complex tasks into simple, ordered steps. Each step works independently, making it easy to find and fix issues.
  • Retries and Conditional Branches: Automatically retry failed steps and choose different paths based on conditions. Like an if/else statement, but for your whole workflow.
  • Pause/Wait States and Resume Triggers: Pause workflows until something happens, like getting an API response or user approval. Continues automatically when ready.
  • Persistent State Management: Safely saves all your workflow data between steps. Keeps track of everything, even if there are errors or delays.
  • Cloud-scale Execution: Runs smoothly in the cloud with multiple workflows at once. Each workflow runs separately without interfering with others.
  • Code-First & LLM-Ready: Define workflows in plain JavaScript code, making them perfect for LLM-assisted development. AI can help write, review, and improve your workflows just like any other code.

Getting Started: Your First Workflow

index.js
import { app } from 'codehooks-js'

const workflow = app.createWorkflow('parityCheck', 'Check if a number is even or odd', {
begin: async (state, goto) => {
state.number = Math.floor(Math.random() * 100)
goto('check', state)
},
check: async (state, goto) => {
const step = (state.number % 2 === 0) ? 'even' : 'odd'
goto(step, state) // branch
},
even: async (state, goto) => {
console.log(`${state.number} is even`)
goto('end', state)
},
odd: async (state, goto) => {
console.log(`${state.number} is odd`)
goto('end', state)
},
end: async (state, goto) => {
console.log('Workflow finished', state)
goto(null, state) // null complete the workflow
}
})

// REST API to start a new workflow instance
app.post('/start', async (req, res) => {
const result = await workflow.start('parityCheck', {"Initial": "state"});
res.json(result);
});

// export app interface to serverless runtime
export default app.init();

The above JavaScript workflow code can also be visualized as a diagram like the Mermaid diagram shown below:

Designed for Developers

  • JavaScript-native: Write workflows in plain JavaScript using async/await. No special syntax to learn - just write normal JavaScript code.
  • Composable: Break workflows into reusable modules that you can import and combine. Add middleware for common functionality like logging or error handling.
  • Serverless: Built for serverless from the ground up. Stores workflow state separately from functions to keep memory usage low.
  • Distributed-safe: Handles concurrent updates safely across multiple workers. Uses atomic operations to prevent data conflicts.

🤖 LLM-Friendly Development

  • Code-First Approach: Since workflows are defined in plain JavaScript, LLMs can easily understand, generate, and modify workflow code. No need to translate between visual tools and code.
  • Self-Documenting: Each step is a named function with clear inputs and outputs, making it easy for LLMs to analyze and explain workflow logic.
  • Pattern Recognition: Common workflow patterns are expressed as standard JavaScript patterns, allowing LLMs to suggest improvements and best practices.
  • Error Prevention: LLMs can help catch common workflow issues like missing state transitions or infinite loops before runtime.

Common Use Cases

  • User Onboarding: Implement multi-step registration flows with validation, OAuth integration, and role-based access control. Handle edge cases like partial completions and timeouts.
  • Approval Flows: Create approval workflows where multiple people need to review and approve something. Track who approved what and when, and send reminders for pending approvals.
  • Data Sync and Async Jobs: Process large datasets with checkpointing and resumable execution. Includes built-in support for rate limiting, batching, and error handling.
  • External Event Triggers: Listen for events from outside sources like webhooks and message queues. Handles duplicate events and ensures reliable processing.

🚀 Ready to Build Smarter Backends?

👉 View the Workflow API docs →