Orchestration puts a central coordinator in charge of a multi-step process. Choreography lets services react to events and drive the next step themselves. When each pattern fits, and how Encore Pub/Sub supports event choreography without inventing a workflow engine.
Orchestration and choreography are two ways to run a business process across microservices. In orchestration, a central component calls each step and owns the branching. In choreography, services emit events and other services decide what to do next, so there is no single conductor process.
Neither pattern is automatically "more microservices." A chatty orchestrator can couple everything to one deployment unit; an unbounded event web can hide the actual sequence until an outage. This guide separates the tradeoffs and shows how Encore Pub/Sub implements the choreography side without pretending to be a durable workflow engine.
An orchestrator (a dedicated service, a state machine or a workflow worker) receives "start order," then calls inventory, payment and shipping in sequence or in a defined parallel graph. It stores where the process is, and compensation logic ("cancel hold," "refund") lives next to that state.
Strengths: one place to read the happy path, easier timeouts and human approvals when the engine supports them, clearer ownership of "the order process." Costs: the orchestrator becomes a dependency for every step, versioning in-flight runs is your problem (or your workflow engine's), and scaling the conductor is separate from scaling the workers.
AWS Step Functions and Temporal are common orchestrators when you need a durable control plane. They are not required for every multi-step API; a single service calling two clients with a database row is still orchestration, just without a product name.
In choreography, the order service commits "OrderPlaced" and publishes an event. Inventory, email and analytics each subscribe. The order service does not call them and does not know how many consumers exist. New consumers appear by adding a subscription.
Strengths: producers stay stable as consumers grow, blast radius of a slow consumer is its own backlog, and teams can ship reactions independently. Costs: the end-to-end sequence lives in the event graph, debugging needs correlation IDs and traces, and an "exactly once" business action requires idempotent handlers under at-least-once delivery.
Amazon SNS and Amazon SQS are a typical cloud implementation: a topic fans out, queues buffer each consumer, dead-letter queues hold poison messages. The application still owns schema versioning and idempotency.
Pick orchestration when one process must enforce a strict sequence, compensate across steps or show a single status API that is the source of truth for the whole run.
Pick choreography when the primary need is fan-out of a domain fact to independent policies (notify, index, bill, train a model) and each consumer can own its failures.
Many systems mix both: a small orchestrator inside a bounded context, and choreography across contexts via events. Dual-write from a database transaction to a bus without an outbox is a common choreography bug; publish only after commit, or use an outbox, so consumers never see events for rolled-back rows.
Encore works alongside the service layout you already have, and declared topics and subscriptions are infrastructure from code. The platform provisions and deploys into your own AWS or GCP account: you declare topics and subscriptions in application code, and Encore provisions the messaging infrastructure in your own cloud on deploy.
Encore does not act as a workflow engine and does not store Temporal-style event history or Step Functions state machines. For choreography, the Pub/Sub APIs give you typed topics, subscriptions, at-least-once or exactly-once delivery settings, retries and dead-letter queues. On AWS that becomes SNS plus SQS with DLQs and an IAM role for the service, per the AWS infrastructure docs. When you need durable orchestration with timers and signals, run Temporal or Step Functions beside the app; when you need fan-out and independent consumers, declare Pub/Sub in Encore.

An order placement that fans out to email and fulfillment:
// order/order.ts
import { api } from "encore.dev/api";
import { Topic } from "encore.dev/pubsub";
import { SQLDatabase } from "encore.dev/storage/sqldb";
const db = new SQLDatabase("order", { migrations: "./migrations" });
export interface OrderPlaced {
orderId: string;
customerId: string;
}
export const orderPlaced = new Topic<OrderPlaced>("order-placed", {
deliveryGuarantee: "at-least-once",
});
export const placeOrder = api(
{ expose: true, method: "POST", path: "/orders" },
async ({ customerId }: { customerId: string }): Promise<{ orderId: string }> => {
const orderId = crypto.randomUUID();
// Persist the order first; publish only after the insert has committed.
await db.exec`
INSERT INTO orders (id, customer_id) VALUES (${orderId}, ${customerId})`;
// If the publish can fail after the commit, relay through an outbox table instead.
await orderPlaced.publish({ orderId, customerId });
return { orderId };
},
);
A second service (or package) subscribes independently; the producer does not import it:
// notify/welcome.ts
import { Subscription } from "encore.dev/pubsub";
import { orderPlaced } from "../order/order";
const _ = new Subscription(orderPlaced, "send-order-email", {
handler: async (event) => {
// Idempotent send keyed by event.orderId
},
});
encore run delivers Pub/Sub locally so both services can be tested without AWS. The same pattern works from the Go Pub/Sub docs. Add object storage, cron or secrets in the same repo when a consumer needs them; vary the resources to the job instead of only queues. An AI coding agent can add a topic and subscription in one pull request and verify the message path under encore run before the deploy creates the cloud resources.
Best fit: Teams that want event choreography as infrastructure from code in TypeScript or Go on their own AWS or GCP account, and who will adopt a dedicated workflow engine only for processes that need durable orchestration.
Orchestration uses a central component that calls services in order and decides what happens next. Choreography has no central conductor: each service publishes and consumes events, and the sequence emerges from those reactions. Orchestration is easier to follow in one place; choreography scales fan-out with looser coupling.
Prefer choreography when many services must react independently to the same fact (signup, payment captured, order shipped), when you want producers unaware of every consumer, and when at-least-once messaging with idempotent handlers is enough. Prefer an orchestrator when one process owns branching, compensation and a single visible timeline.
Pub/Sub delivers events to subscribers with retries and dead-letter queues, while a workflow engine such as Temporal stores durable control state, timers and signals so a process can resume after days. Many backends only need Pub/Sub plus a status table; reach for a workflow engine when you need that durable control plane.
Declare a Pub/Sub topic and one subscription per reacting service in TypeScript or Go. Publish after the state change commits, keep handlers idempotent, and deploy: on AWS Encore provisions SNS and SQS (with dead-letter queues) and an IAM role for the service. encore run delivers messages locally so you can test the path before cloud deploy.
Deploy to your cloud on AWS and Google Cloud
without managing infrastructure
Encore lets developers and agents define application infrastructure directly in code, then automatically provisions it from local development to production in your AWS or GCP account.