Designing a Passively Safe API
43 points
4 days ago
| 6 comments
| danealbaugh.com
| HN
awildfivreld
4 hours ago
[-]
If anyone here wants to do this but don't want to implement all of this yourselves, this "field" is called Durable Execution. Frameworks such as Temporal, Restate and DBOS do a lot of the heavy lifting to get the idempotency, exactly once and recovery to a known state logic here.
reply
compressedgas
3 days ago
[-]
> In APIs, passively safe means failures (crashes, timeouts, retries, partial outages) can't produce duplicate work, surprise side effects, or unrecoverable state.

I thought that was what 'idempotent' meant.

reply
omnicognate
32 minutes ago
[-]
Idempotence of an operation means that if you perform it a second (or third, etc) time it won't do anything. The "action" all happens the first time and further goes at it do nothing. Eg. switching a light switch on could be seen as "idempotent" in a sense. You can press the bottom edge of the switch again but it's not going to click again and the light isn't going to become any more on.

The concept originates in maths, where it's functions that can be idempotent. The canonical example is projection operators: if you project a vector onto a subspace and then apply that same projection operator again you get the same vector again. In computing the term is sometimes used fairly loosely/analogistically like in the light switch example above. Sometimes, though, there is a mathematical function involved that is idempotent in the mathematical sense.

A form of idempotence is implied in "retries ... can't produce duplicate work" in the quote, but it isn't the whole story. Atomicity, for example, is also implied by the whole quote: the idea that an operation always either completes in its entirety or doesn't happen at all. That's independent of idempotence.

reply
dalbaugh
2 days ago
[-]
It's mostly semantics. Passive safety is the "why" while idempotency is the "how".
reply
locknitpicker
49 minutes ago
[-]
Idempotence is a trait of an operarion. Operations are idempotent, but systems were passive.

You don't have idempotent crashes.

reply
vaylian
2 hours ago
[-]
> I'm in the process of migrating Augno's monolithic API to a microservices architecture.

Didn't we get to the point where we realized that microservices cause too much trouble down the road?

reply
locknitpicker
1 hour ago
[-]
> Didn't we get to the point where we realized that microservices cause too much trouble down the road?

That's a largely ignorant opinion to have. Like any architecture, microservices have clear advantages and tradeoffs. It makes no sense to throw vague blanket statements at an architure style because you assume it "causes trouble", particularly when you know nothing about requirements or constraints and all architectures are far from bullet proof.

reply
srinath693
1 hour ago
[-]
“Make the safe path the easiest path” is a great design principle. This should probably be a default mental model for public API design.
reply
vbezhenar
3 hours ago
[-]
That sounds like a lot of over engineering and a good way to never complete the project. Perfect is the enemy of good.
reply
dxdm
2 hours ago
[-]
It sounds like a good way to make sure you don't overcharge your customers when handling such requests at scale. Failure and duplication will happen, and when serving enough requests will happen often enough to occupy engineering with investigation and resolution efforts forwarded from customer support.

Being prepared for these things to happen and having code in place to automatically prevent, recognize and resolve these errors will keep you, the customers and everyone in between sane and happy.

reply
michalc
2 hours ago
[-]
Hmmm... depends on the project / phase of the project?

I am particularly not a fan of doing unnecessary work/over engineering, e.g. see https://charemza.name/blog/posts/agile/over-engineering/not-..., but even I think that sometimes things _are_ worth it

reply
locknitpicker
59 minutes ago
[-]
> That sounds like a lot of over engineering and a good way to never complete the project. Perfect is the enemy of good.

Strong disagree. Addressing expectable failure modes is not over engineering. It's engineering. How do you put together a system without actually thinking through how it fails, and how to prevent those failure scenarios from taking down your whole operation?

reply
user3939382
2 hours ago
[-]
From TFA “Making some tasks asynchronous”

I have bad news for everyone. Nothing in computing is synchronous. Every instance we pretend it’s not and call it something else you have a potential failure under the right circumstances.

The more your design admits this the safer it will be. There are practical limits to this which you have to determine for yourself.

reply
locknitpicker
56 minutes ago
[-]
> I have bad news for everyone. Nothing in computing is synchronous.

I think you need to sit this one out. This sort of vacuous pedantry does no one any good, and ignores that it's perfectly fine to model and treat some calls are synchronous, including plain old HTTP ones. Just because everything is a state machine this does not mean you buy yourself anything of value by modeling everything as a state machine.

reply