Stop orchestrating distributed systems the hard way
Most distributed systems don’t break because of business logic.
Stop orchestrating distributed systems the hard way

Most distributed systems don’t break because of business logic.
They break because of everything around it.
Retries scattered across services. Cronjobs trying to “heal” inconsistent states. Glue code that nobody fully understands anymore.
I’ve seen this pattern repeat itself across different systems and scales.
And it always converges to the same place:
orchestration becomes implicit, fragile, and hard to reason about.
The problem nobody owns
Let’s say you have a simple flow:
- create an order
- charge the user
- reserve inventory
- send confirmation
Looks straightforward.
Until it isn’t.
- payment succeeds, inventory fails
- inventory succeeds, email fails
- a service times out but actually completed
- a retry runs twice
At that point, you don’t have a flow anymore.
You have a distributed system where each part is doing “something” — but no part knows the whole.

What’s actually happening
The flow didn’t disappear.
It just stopped existing as something explicit.
It got split across:
- service-to-service calls
- retry policies
- message queues
- background jobs
Each component handles a fragment of the workflow.
No component owns it.
How we usually “solve” this
Most teams don’t implement orchestration explicitly.
They assemble one indirectly using:
- event choreography (Kafka, SNS, etc.)
- retries inside each service
- cronjobs scanning for “incomplete” states
- outbox pattern everywhere
This works — but only in the sense that the system keeps moving.
The trade-offs are real
Over time, you start paying for it:
- you lose visibility of the flow
- debugging turns into log archaeology
- state becomes implicit and fragmented
- compensation logic diverges between services
And the most important one:
there is no single place that owns the execution

“Just use a workflow engine”
That’s the usual advice.
And it’s not wrong.
Tools like Temporal solve this problem extremely well.
But they come with real trade-offs:
- SDK-heavy integration
- tight coupling to their runtime model
- operational overhead
- a different way of building services
They don’t just solve orchestration.
They introduce a platform.
And sometimes, that’s more than you want.
So most teams stay in the middle
Not fully implicit. Not fully structured.
Just enough orchestration to work. Not enough to reason about.
A different question
Instead of asking:
“how do we orchestrate this better?”
Try asking:
“why is orchestration so hard to adopt in the first place?”
What if it wasn’t a platform?
What if orchestration was:
- not embedded in your services
- not tied to an SDK
- not coupled to a runtime
What if it was just something you could call?
What if orchestration was just an HTTP API?
That’s the idea behind Trama.
Not to replace how you build services.
But to give you a place where the flow actually exists.
Instead of:
- encoding the workflow across services
- inferring execution from logs
You:
- define the workflow
- execute it
- query its state
How it works in practice
You define a flow:
- call service A
- then service B
- branch on a condition
- compensate on failure
And then you execute it.
Trama takes care of:
- retries
- execution ordering
- state persistence
- resuming after failure

Not by hiding complexity.
But by centralizing it.
The important shift
The biggest change is not technical.
It’s conceptual.
Orchestration becomes explicit.
You can:
- see the flow
- reason about it
- debug it
- evolve it
Without reconstructing everything from logs.
Async is not a special case
One of the hardest parts of distributed systems is dealing with async:
- waiting for external systems
- webhooks
- long-running operations
Most systems handle this with:
- polling
- timeouts
- manual state tracking
Trama treats this as part of the workflow.
A step can:
- pause
- wait for a callback
- resume safely
Without losing state. Without hacks.

When this makes sense
Use it when:
- you have multi-step workflows across services
- you need retries and compensation
- you depend on unreliable or external systems
- you care about understanding what’s happening
When it doesn’t
Don’t use it if:
- your flow is simple
- everything is synchronous and reliable
- orchestration fits cleanly in a single service
This is not a default choice.
It’s a tool for a specific class of problems.
Why I built this
Not because workflows are a new idea.
But because of how often I’ve seen the same failure pattern:
- things fail in non-obvious ways
- retries create more problems than they solve
- understanding a flow takes hours
And the root cause is always the same:
the system is executing a workflow but has nowhere to represent it
And there’s another pattern I’ve seen over and over:
teams consider adopting a workflow engine
but the migration never happens
- the effort is too high
- the integration is invasive
- it requires rewriting working systems
so they stick with what they have and keep adding patches on top
- cronjobs
- retries
- manual fixes
That’s why Trama is API-first.
- No SDKs.
- No runtime dependencies.
- No framework lock-in.
Just HTTP.
You don’t replace your system.
You plug into it.
Final thought
Distributed systems are not hard because of business logic.
They are hard because of coordination.
And most of the time, we coordinate things in ways that are:
- implicit
- fragmented
- fragile
Maybe the problem is not orchestration itself.
Maybe it’s how we’ve been trying to do it.
👉 GitHub: https://github.com/thiagoribeiro/trama 👉 Site: https://trama.run
메타데이터
- post_id
- 4e92b9be064b
- slug
- stop-orchestrating-distributed-systems-the-hard-way-4e92b9be064b
- url
- https://medium.com/@thiago-azeredo/stop-orchestrating-distributed-systems-the-hard-way-4e92b9be064b
- canonical_url
- https://medium.com/@thiago-azeredo/stop-orchestrating-distributed-systems-the-hard-way-4e92b9be064b
- author_url
- https://medium.com/@thiago-azeredo
- status
- ok
- fetched_at
- 2026-06-21 07:44:09