Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I think the "embrace failure" supervisor model in BEAM is a superior design for mission-critical systems (such as cell networks, where it originated) while resulting in literally a ton less boilerplate. You just code the "happy path" and done. Any errors are logged and the process instantly restarted by the supervisor, you can follow up on them if they present a problem.

If you were to code just this "happy path" in Go, it would actually be the unhappy path, because you'd have silent errors resulting in indeterminate state (read: horrible bugs to troubleshoot). If you believe programming is mostly about managing all possible state (as I do), then Go's strategy is way too explicit. In Erlang/Elixir/BEAM's case, as soon as state goes off the rails (read: encounters something the programmer didn't anticipate), it's logged and restarted by its supervisor process almost instantly. (and there are of course strategies for repeated restarts)




People keep saying this and I struggle to understand how this represents good design. In any language I can always just eat the error and keep going, or eat the error and restart.

That doesn't fix the error, and it doesn't imply the program will work correctly.


> In any language I can always just eat the error and keep going, or eat the error and restart.

Defer to pmarrek on what they meant, but to me it's an issue of practical programming.

In a choice between "I will tell you what to do about errors" vs "I will assume you only crash and restart on any error", I've found the later to be far more efficient.

The former generally leads to a rat's nest of never ending error specialization as unexpected or rare stuff bubbles up in UAT or down the road in prod.

Which isn't to say there's a right answer. There's always going to be particular situations where of course you should use one or the other.

But on the whole, as a philosophical default, fail-and-recycle-on-all-errors is a helluva lot easier to spec, code, test, and maintain for me.


I think you need to try it out to see what the big deal is. It's pretty liberating.

The thing is, there will always be the "unknown unknown" bugs, the ones you didn't even think to anticipate, and Erlang/Elixir/BEAM will always win out in a behavior contest on those vs. in Go, because it is built to anticipate any possible error, not just the possibilities you're aware of.


so the argument is that there are (broadly) two classes of errors. ones that happen all the time and ones that happen hardly ever

the erlang strategy is to make it possibly to continue from a known good state when the latter happens where chances are it won't happen again. the errors that happen all the time you will encounter early/often enough that you can work out how to handle/fix them

the result of this strategy is you pretty much never write code that handles the unexpected. it turns out that's a lot of code to not have to write


Those supervisors don't always handle the errors the way you want and can't always be implemented without diminishing overall performance. It's a trade-off.


There's nothing stopping you from handling the errors, though. It's just that the ones you didn't anticipate won't typically bring down the system.


It's convenient to write this sort of optimistic code that Erlang encourages, but the error messages are often not very helpful. You'll often end up with a pattern matching failure and stacktrace that isn't very clear compared to a hand-written error message that you would get in Go.




Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: