Erlang & Elixir DISCUSSION

Why are Erlang and Elixir processes so much cheaper than operating system threads?

Started by manh Erlang processesBEAM schedulerlightweight concurrencyper-process garbage collectionmessage passing
4 replies 248 views 5 participants
Latest activity · 30 Sep 2026

Why are Erlang and Elixir processes so much cheaper than operating system threads?

manh Erlang & Elixir Forum
#1

I keep reading that an Erlang or Elixir system can run hundreds of thousands of processes on one machine, and that starting one process per connection or per device is normal. With OS threads in C or Java I would be careful about creating even a few thousand.

Technically, what makes a BEAM process so much lighter than a thread, how does the VM schedule them all, and what are the costs that I should still keep in mind?

Community replies 4

Re: Why are Erlang and Elixir processes so much cheaper than operating system threads?

#2

A BEAM process is a data structure inside the virtual machine, not a kernel object. It consists of a small process control block, a mailbox, and one block of memory that holds both its stack and its heap and grows on demand. A freshly spawned process occupies a few hundred machine words; the efficiency guide in the Erlang documentation gives the exact figure for each release, and it is in the region of 2 to 3 KB on a 64-bit system. At that size 100,000 idle processes need a few hundred megabytes.

An OS thread reserves a stack that is typically measured in megabytes of address space, and creating or switching one involves the kernel. Spawning a BEAM process is a memory allocation and a queue insertion in user space.

Re: Why are Erlang and Elixir processes so much cheaper than operating system threads?

#3

Scheduling is done by the VM. By default it starts one scheduler thread per CPU core, each with a run queue of ready processes, and work is migrated between queues to balance load. A process does not run until it chooses to yield; it is given a budget of a few thousand reductions (roughly, function calls) and is preempted when the budget is used up. That is why one process stuck in a long computation cannot freeze the others, which a cooperative design such as a single-threaded event loop cannot guarantee.

A process waiting in receive costs no CPU at all; it is simply not in any run queue until a message arrives.

Re: Why are Erlang and Elixir processes so much cheaper than operating system threads?

#4

Memory isolation is the other half. Each process has its own heap, and processes share nothing, so there are no locks around data and garbage collection is done per process. Collecting a small private heap takes very little time and does not stop any other process, so there is no global pause that grows with total memory. A short-lived process often never runs a collection: when it exits, its whole heap is released at once.

The price is that a message sent to another process is copied into the receiver's heap. The exception is large binaries (above 64 bytes), which are reference-counted and shared, so passing a big payload around is cheap.

Re: Why are Erlang and Elixir processes so much cheaper than operating system threads?

#5

Costs to keep in mind. Copying means that sending a large nested term to many processes is expensive; send a reference or an identifier, or keep the data in ETS. A process handles one message at a time, so a single process that everything talks to becomes a bottleneck however many cores you have. Raw number crunching on the BEAM is slower than native code, and native functions (NIFs) that run for a long time block a scheduler unless they are written for the dirty schedulers.

There is also a configurable ceiling on the number of processes, set with the +P emulator flag; erlang:system_info(process_limit) shows the current value and erlang:system_info(process_count) how many exist. Use one process per concurrent activity (a connection, a device, a job), not one per data object.

TEP COMMUNITY