Erlang's let-it-crash philosophy - applicable elsewhere?
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
Erlang's let it crash philosophy is often misunderstood as a license to ignore errors. That is not what it means. The real idea is to stop writing fragile recovery logic inside every component and instead build systems where failing components are isolated, replaceable, and supervised.
That design absolutely applies outside Erlang, but only if the rest of the architecture supports it. If a crash destroys irreplaceable in-memory state or takes down the whole process, then let it crash is just a bug with a slogan attached.
What Let It Crash Really Means
In Erlang and OTP, small processes do one job, avoid shared mutable state, and can be restarted by supervisors. The process is expected either to finish correctly or to fail fast. Recovery happens one level up in the supervision tree.
This works because three conditions are built in:
- Isolation between units of work.
- Cheap restart of failed units.
- State stored in a place that can be reconstructed or recovered.
Without those conditions, crashing is expensive and dangerous.
Where the Philosophy Transfers Well
The approach works well in systems that already separate control flow from failure recovery:
- Background job workers that can be retried from a queue.
- Microservices running behind a restart policy in Kubernetes or systemd.
- Actor-style runtimes such as Akka or Orleans.
- Stateless request handlers where a failed request can be retried safely.
It is also useful at module level. Even in a regular application, it is often better for a component to reject an impossible state immediately than to limp forward after corrupting data.
A Simple Supervisor Example Outside Erlang
Python does not give you Erlang supervision out of the box, but you can model the same idea with a parent process that restarts a worker:
This is not OTP, but it shows the principle. The worker does not contain complicated self-repair logic. The supervisor decides whether and how to restart.
What Makes This Safe
The philosophy only works when restart is cheaper than local repair. That means you should externalize important state and keep worker startup predictable.
For example, a request handler that reads from a database, computes a response, and writes structured logs is a good fit. If the process crashes, a replacement can serve the next request without needing hidden state from the dead process.
A trading engine keeping critical state only in memory is a poor fit. If that process crashes, blind restart may lose or duplicate business actions unless the system was designed around durable event logs and idempotency.
Good Uses in Non-Erlang Systems
The idea translates well into day-to-day engineering practices:
- Fail fast on invariant violations instead of guessing.
- Use supervisors, process managers, or orchestration platforms to restart units.
- Keep services stateless where possible.
- Make work idempotent so retries are safe.
- Persist state before acknowledging success.
Kubernetes, for example, makes restart policies easy, but Kubernetes alone does not give you Erlang semantics. You still have to design services so a restarted container can recover cleanly.
Where It Does Not Transfer Cleanly
Some environments punish crashing:
- User-facing desktop apps where repeated crashes destroy trust.
- Embedded control systems with strict real-time behavior.
- Libraries that run in another host process.
- Code paths performing irreversible side effects without idempotency.
In those cases, defensive validation and local error handling still matter. The lesson from Erlang is not always crash. The lesson is crash small, crash safely, and recover at the right boundary.
Common Pitfalls
The biggest mistake is applying the philosophy without supervision. If a process crashes and nothing restarts it, you have copied only the failure half of the model.
Another mistake is hiding non-durable state inside a worker and assuming restart is harmless. If restart loses business state, the system was not ready for let it crash.
Teams also misuse the phrase to justify missing validation. Fast failure is valuable, but only after you have drawn a boundary between recoverable input errors and truly impossible states.
Finally, do not build infinite restart loops without backoff or escalation. A supervisor should know when to stop retrying and mark the system unhealthy.
Summary
- '
Let it crashmeans fail fast inside isolated components and recover through supervision.' - The idea works outside Erlang when restart is cheap and critical state is durable.
- It fits stateless workers, queued jobs, and actor-like systems better than monolithic stateful processes.
- Crashing is not a substitute for validation, idempotency, or supervision.
- The philosophy transfers well only when the architecture is designed for safe restart.
Related reading
- Error creating Kafka topic - replication factor larger than available brokers
- Error when trying to 'mvn clean install' Gerrit's replication plugin
- Error while trying to configure ArangoDB replication
- Eureka and Kubernetes
- Error-Handling in Swift-Language
- error -215 ssize.width 0 ssize.height 0 in function resize
- Eureka and Kubernetes
- Event driven microservices with message brokers (e.g. Kafka) vs reactive programming (RxJava, Project Reactor) plus improved protocols (RSocket)

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.