Skip to content

Microservices Orchestration Example

Orchestrating a complex process across multiple microservices with a Saga.

The Scenario: Order Fullfillment

  1. Inventory Service: Reserve items (Microservice A).
  2. Payment Service: Charge customer (Microservice B).
  3. Shipping Service: Create shipment (Microservice C).

The Code

ts
import { create } from "@eddiecbrl/orchestrix";
import axios from "axios";

const fulfillmentFlow = create("order-fulfillment")

  .step("reserve-inventory", async (ctx) => {
    const res = await axios.post("http://inventory-svc/reserve", { 
      items: ctx.input.items,
      orderId: ctx.input.orderId 
    });
    ctx.set("reservationId", res.data.id);
  }, {
    compensate: async (ctx) => {
      const id = ctx.get("reservationId");
      await axios.post(`http://inventory-svc/release/${id}`);
    }
  })

  .step("process-payment", async (ctx) => {
    await axios.post("http://payment-svc/charge", {
      amount: ctx.input.total,
      orderId: ctx.input.orderId
    });
  }, {
    retries: 3,
    backoffFactor: 'exponential'
  })

  .step("create-shipment", async (ctx) => {
    await axios.post("http://shipping-svc/ship", {
      orderId: ctx.input.orderId,
      address: ctx.input.address
    });
  }, {
    compensate: async (ctx) => {
      // If shipping was created but something later fails, cancel shipment
      await axios.post(`http://shipping-svc/cancel/${ctx.input.orderId}`);
    }
  });

Highlights

  • Centralized Control: The entire business logic for order fulfillment is visible in one place, even though it spans three different services.
  • Distributed Consistency: The Saga Pattern ensures that if the payment fails, the inventory is released. If the shipping creation fails, the payment is refunded (if a compensation was added to that step) and inventory is released.
  • Service Decoupling: Each microservice only needs to provide its core functionality and a compensation endpoint; they don't need to know about each other.

Released under the MIT License.