Distributed Workflows
When your application grows, you need to ensure your workflows are safe across multiple instances and can handle high concurrency.
Cross-Instance Safety
By default, Orchestrix runs workflows in-process. To ensure that two different instances of your app don't process the same request at the same time, you must use Distributed Idempotency.
Redis Adapter
The Redis adapter uses atomic operations to "lock" an idempotency key before execution.
ts
import { createRedisIdempotencyStore } from "@eddiecbrl/orchestrix/adapters/redis";
const store = createRedisIdempotencyStore(redisClient);
const flow = create("my-flow", { idempotency: store });Handling Concurrency
If a second request with the same idempotency key arrives while the first one is still running:
- Default: Orchestrix returns a
runningstatus and does not re-execute. throwIfRunning: You can configure it to throw an error so your API can return a409 Conflict.
ts
await flow.run(input, {
key: "abc",
throwIfRunning: true
});Resilience vs. Throughput
- More Retries: Improves resilience but increases the "hold time" of resources and can decrease overall throughput.
- Short Timeouts: Improves throughput and fail-fast behavior but can lead to more frequent compensations if your downstream services are just slightly slow.
The Role of Message Queues
Orchestrix is often used inside a consumer of a message queue (like RabbitMQ or SQS).
- Message Arrives: Queue delivers message to Worker instance.
- Orchestrix Runs: The worker uses Orchestrix to execute the multi-step business logic.
- Ack/Nack: Based on the
FlowResult, the worker acknowledges the message or returns it to the queue for a full retry.
Using Orchestrix's internal retries before returning the message to the queue is usually more efficient for transient network issues.