Chaturmind
LearnDSASystem DesignDevOpsEngineering GrowthBlog
Start learning
Chaturmind

Structured learning paths for engineers who want to go deep. Written by practitioners.

Learn

  • Java
  • DSA
  • System Design
  • Spring Boot
  • AI / ML
  • DevOps
  • Engineering Growth

Company

  • Blog
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Chaturmind. All rights reserved.

Built for engineers who want to go deep.


← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
Chaturmind
← Low-Level Design & Design Patterns

OOP Fundamentals & SOLID Principles

  • Object-Oriented Design Refresher
  • Single Responsibility & Open/Closed
  • Liskov Substitution & Interface Segregation
  • Dependency Inversion

Creational Design Patterns

  • Singleton Pattern
  • Factory & Abstract Factory
  • Builder Pattern
  • Prototype Pattern

Structural Design Patterns

  • Adapter & Facade
  • Decorator Pattern
  • Composite & Proxy
  • Bridge & Flyweight

Behavioral Design Patterns

  • Strategy Pattern
  • Observer Pattern
  • Command Pattern
  • Template Method
  • State Pattern
  • Chain of Responsibility
  • Iterator & Mediator
  • Visitor Pattern

Machine Coding Exercises

  • Parking Lot — Requirements & Class Design
  • Parking Lot — Implementation
  • Elevator System — Requirements & Class Design
  • Elevator System — Implementation & Scheduling
  • Library Management System
  • Tic-Tac-Toe / Board Game Design
  • Chess Engine Design
  • Vending Machine Design
  • ATM System Design
  • In-Memory Rate Limiter
  • Thread-Safe LRU Cache
  • Connection Pool Design
  • Producer-Consumer Class Design
  • Movie Ticket Booking System
  • Hotel Reservation System
  • Airline Booking / Seat Selection System
  • Splitwise / Expense Sharing System
  • Design a Logging Framework
  • Design a Notification/Observer-Based Pub-Sub
  • Design a Cache with Pluggable Eviction Policy
  • Design Snake and Ladder
  • Design a Card Game Framework
  • Design an Inventory Management System
  • Restaurant Management System
  • Food Delivery Order Matching
  • Design a Shopping Cart & Checkout Flow
  • Design a Recommendation Engine
  • Design a Job Scheduler
  • Design a Circuit Breaker
  • Design a Distributed ID Generator
  • Design a Pub-Sub Message Broker
  • Design Twitter/X
  • Multi-Pattern Problem: Design a Ride Booking Class Model
  • Multi-Pattern Problem: Design a Food Ordering Class Model
  • Design an Authentication/Authorization Module
  • Design a Form/Survey Builder
  • Design a Meeting Room / Calendar Booking System
  • Design a Search/Filter Engine for an E-Commerce Catalog
  • Design a Voting/Polling System
  • Design a Retry Mechanism with Backoff
  • Design a Health Check Aggregator
  • Design a Feature Flag System
  • Design a Config Management Client
  • Design a Leader Election Algorithm
  • Design a Distributed Counter
  • Design a Bloom Filter
  • Design a Consistent Hashing Ring
  • Design a Distributed Tracing Library
  • Design a Metrics Collection Library
  • Design an Audit Logging Framework
  • Design a Plugin/Extension System
  • Design a Workflow Engine
  • Multi-Pattern Capstone: Design a Food Delivery App
HomeLearnSystem DesignLow-Level Design & Design PatternsMachine Coding Exercises
✓ FreeAdvanced· 7 min read

Design a Workflow Engine

Workflow, Step, WorkflowExecutor, and WorkflowContext as the core classes, sequential execution with output-based branching, and the direct conceptual link to the saga pattern orchestrator.

Published September 23, 2026


Design a Workflow Engine

Core classes

interface Step { StepResult execute(WorkflowContext context); }
class StepResult { boolean success; String nextStepId; /* null means "use default next step" */ }
class WorkflowContext { Map<String, Object> data = new HashMap<>(); } // shared state passed between steps

class Workflow {
    String id;
    Map<String, Step> steps; // stepId -> Step
    String startStepId;
}

class WorkflowExecutor {
    void run(Workflow workflow, WorkflowContext context) {
        String currentStepId = workflow.startStepId;
        while (currentStepId != null) {
            Step step = workflow.steps.get(currentStepId);
            StepResult result = step.execute(context);
            if (!result.success) { handleFailure(workflow, currentStepId, context); break; }
            currentStepId = result.nextStepId;
        }
    }
}

Step as an interface is what lets a workflow be composed of independently-testable, independently-reusable units — each step only knows how to do ITS job and decide the next step ID; it has no awareness of the workflow's overall shape.

Sequential execution with branching

class CheckInventoryStep implements Step {
    public StepResult execute(WorkflowContext ctx) {
        boolean inStock = inventoryService.checkStock((String) ctx.data.get("productId"));
        ctx.data.put("inStock", inStock);
        return new StepResult(true, inStock ? "reserveInventory" : "notifyOutOfStock"); // branches based on OUTPUT
    }
}

A step's nextStepId being determined by ITS OWN execution result (not a fixed, hardcoded sequence baked into the WorkflowExecutor) is what enables genuine BRANCHING — the same workflow definition can take different paths depending on what happens at each step, without the executor itself needing any workflow-specific branching logic. The executor stays generic; all the domain-specific branching logic lives inside individual steps.

The direct conceptual link to the saga pattern orchestrator

This workflow engine's shape — a sequence of steps, each with a defined outcome, executed by a central coordinator tracking progress — is STRUCTURALLY the same shape as the saga pattern's orchestrator (Data Ownership Model's cross-service-write coordination) — a saga IS a workflow, specifically one where each step is a call to a DIFFERENT SERVICE'S local transaction, and "failure handling" means running COMPENSATING actions for already-completed steps rather than simply stopping. Building this generic workflow engine here is what makes a saga orchestrator's design legible as "a workflow engine, specialized for cross-service transactions with compensation" rather than an entirely separate concept to learn from scratch.

Follow-up questions this topic invites — and their answers

Q: How would you add compensating-action support to turn this into a genuine saga orchestrator? A: Each Step would additionally expose a compensate(WorkflowContext) method; WorkflowExecutor would need to track which steps have ALREADY SUCCEEDED, and on a later step's failure, walk backward through the completed steps calling their compensate() methods in reverse order — directly implementing the Payment System / E-Commerce Checkout saga examples discussed earlier in this course.

Q: Does this design support PARALLEL steps (two independent steps running at once), or only sequential? A: As written, purely sequential — supporting parallelism would require StepResult to be able to specify MULTIPLE next steps, and WorkflowExecutor to track multiple concurrently-in-progress branches (and typically a JOIN point where they must all complete before proceeding) — a meaningfully more complex executor, though the same Step/WorkflowContext building blocks still apply.

Q: How would a long-running workflow (spanning hours or days, e.g. waiting for a human approval step) be handled, given this in-memory implementation? A: The WorkflowContext and current-step-position would need to be PERSISTED between steps (not held purely in memory across the while loop), letting execution PAUSE and RESUME later — a durable workflow engine (like Temporal or AWS Step Functions in practice) is built around exactly this persistence requirement, which this simplified in-memory version deliberately sets aside to focus on the core step/branching logic.

Q: Should WorkflowContext's data map be typed, rather than Map<String, Object>? A: For a real production system, yes — a loosely-typed context risks a step reading a key that was never set, or casting to the wrong type, both only discovered at runtime; a more robust design would use a typed context object per workflow (or at minimum, well-documented, validated keys), trading some genericity for real compile-time safety.

Previous

Design a Plugin/Extension System

Next

Multi-Pattern Capstone: Design a Food Delivery App

AI Tutor

Lesson: Design a Workflow Engine

Quick actions

AI responses can be inaccurate. Verify critical information.