C:\2010S\SYSTEMD.TXT

2010

systemd: The Computer Needn't Wait in Line

The experimental 2010 init system separated service availability, startup order, and supervision to make Linux boot a different kind of problem.

7 min readCovers April 2010 experimental announcement; 2010–2011 early documentationSoftware That Shaped the 2010s

A computer can spend its first moments waiting for programs that are themselves waiting for other programs. The disk light supplies reassurance. It doesn’t explain whose turn it is.

Booting an operating system means arranging a usable collection of services: logging, communication, storage, networking, and whatever else that machine needs. Starting their executables is only part of the job. Their relationships matter, and somebody must notice when one dies after the reassuring startup message has disappeared.

On April 30, 2010, Lennart Poettering introduced systemd as an experimental replacement for Linux’s init machinery. The announcement described version 0 and warned of limited testing. This was a proposal with running code, rather than a declaration that every Linux distribution had already changed its mind.1

The project’s early development included Kay Sievers. Poettering’s 2013 retrospective dates Fedora 15’s adoption to May 24, 2011. That separates the public experiment from a distribution shipping it as its normal init system.2

The interesting idea was to give startup relationships somewhere better to live than the accidental sequence of commands in a shell script. An order written down by a person may be necessary. It may also be yesterday’s workaround wearing a number.

Three statements that sound alike

Imagine an invented catalogue service that needs a message bus. These statements describe different requirements:

  • The catalogue needs the bus to be included in the startup operation.
  • The catalogue should start after the bus.
  • The catalogue needs a working reply from the bus before it can finish initialization.

The first concerns membership: which services should be present? The second concerns order: when should their startup jobs run? The third concerns actual communication. Treating all three as one instruction can produce unnecessary waiting or an unreliable start.

Early systemd configuration distinguished requirement relationships, such as Requires and Wants, from ordering relationships, such as After and Before. A named unit described a managed resource; services, sockets, devices, mounts, and grouping targets could participate in the arrangement.1

A useful consequence is that an ordering instruction needn’t create a service. Poettering’s October 2010 conversion guide explicitly explains that After= alone doesn’t pull its named unit into the startup operation.3

Suppose our catalogue is useful even without a printer. It can have a preferred order relative to a printer service without demanding that every machine run one. The dependency model has room to express that distinction. A laptop shouldn’t need to summon the office printer merely to prove that it understands chronology.

This also makes the configuration inspectable. If a service participates in a startup transaction, its relationships are data the manager can examine. A command hidden halfway through a script requires a different kind of investigation: reading the program and working out which path ran.

Put some numbers on the waiting

Consider four fictional services with deliberately small startup durations. Logging takes two seconds, a bus takes three, a catalogue takes four, and a printer takes one. The bus follows logging. Both catalogue and printer follow the bus.

Running everything serially takes ten seconds:

2+3+4+1=10.2 + 3 + 4 + 1 = 10.

Once the bus is ready at second five, catalogue and printer can start together. Catalogue finishes at second nine; printer finishes at second six. The whole dependency schedule therefore takes nine seconds.

ServiceDurationDependency-parallel startFinish
Logging2 s0 s2 s
Bus3 s2 s5 s
Catalogue4 s5 s9 s
Printer1 s5 s6 s

These numbers are an original scheduling model, checked with a short Python program. They aren’t measurements of Fedora, systemd, or any historical computer. The model assumes no contention for processors or storage and no hidden work outside the four durations.

Three conceptual service startup schedules

Original illustration, 2026. Invented durations compare serial scheduling, dependency scheduling, and an ideal overlap bound. Not a historical boot chart.

Parallelism doesn’t mean a fourfold improvement just because there are four services. The longest necessary chain dominates this example. Adding processors cannot remove a relationship that says one service must wait for another to finish.

There is another question, though: does the client truly need the server’s initialization to finish before the client’s own initialization can even begin? It might need only a place to send a request. That is a smaller requirement, and it suggests a different schedule.

Open the door before staffing the office

A socket is a communication endpoint. Ordinarily a server creates one, binds it to an address, and listens for clients. With socket activation, the service manager establishes the endpoint and passes it to the server when the server starts. The endpoint’s lifetime can therefore differ from the executable’s lifetime.4

Our fictional catalogue can begin its independent setup while a request waits for the bus to handle it. The kernel provides buffering and, when necessary, makes a caller wait. This moves some synchronization into the communication mechanism itself.

If all four services’ listed work were genuinely independent after their endpoints existed, the ideal lower bound in our model would be four seconds, the longest duration. Real services perform requests during initialization, and those requests may block. Four seconds is an illustrative bound, not a prediction that installing systemd converts ten seconds into four.

That qualification is the useful part of the example. Overlap becomes possible when a previously imposed startup barrier is stronger than the actual communication requirement. It doesn’t make dependencies disappear from the work being done.

A client sends to a manager-owned socket before a service consumes the request

Original conceptual illustration, 2026. Shows endpoint ownership and queued work, not systemd’s complete internal implementation.

The 2011 developer guide explains how a service receives inherited file descriptors, beginning at descriptor 3, through systemd’s socket-passing convention. The service must know how to use them; an arbitrary program doesn’t become socket activatable simply because an administrator wishes it well.4

There are also limits to the queue. A client may block when buffers fill. A protocol that demands an immediate response still has to wait for a functioning server. Keeping a listening socket available doesn’t guarantee that an already running request survives a crash or that its side effects happen exactly once.

I find this more persuasive than a promise of instant boot. The mechanism changes what must wait, and gives the waiting a defined place. That is an engineering claim one can examine.

“Started” requires a definition

A manager can successfully launch a program before that program is ready to do useful work. A server may still be reading configuration, recovering files, or registering itself with another service.

The October 2010 guide demonstrates this through the ABRT crash-reporting daemon. Its initial conversion uses traditional forking behavior. A revised service instead runs in the foreground and uses acquisition of its D-Bus name as the readiness signal.3

For our catalogue, an equivalent conceptual rule might say that it is ready when it has registered its communication name. Whether that is sufficient depends on the catalogue’s own contract. Registration performed too early merely gives the manager an efficiently delivered misunderstanding.

This distinction matters beyond boot speed. A dependent program may fail if its predecessor exists as a process but can’t accept requests. Restart policy can also misbehave when a manager can’t reliably identify the main process or its state.

The lesson is modest: a readiness signal should describe the condition clients actually require. Process existence is a convenient observation. It isn’t automatically the right condition.

Keep the service together after startup

Traditional daemon behavior could detach a process from the parent that launched it. Children and grandchildren complicated the job of deciding which processes belonged to a service.

The original announcement used Linux control groups, or cgroups, to track service processes. Descendants inherit group membership; an ordinary unprivileged child can’t simply evade that grouping by forking again.1

Think of an invented web service with a main process and three workers. Stopping only the main process could leave workers holding resources or continuing jobs. A service-level group provides a handle for managing the collection.

Grouping isn’t the same as a complete security boundary. Privilege, resource controllers, shutdown policy, and application behavior still matter. But the administrative unit now corresponds more closely to the thing the operator intended to stop.

Supervision also needs memory. The August 2010 administrator guide describes retained service status, including unsuccessful exits, timeouts, and abnormal termination. It shows systemctl presenting the state after boot, when the rapidly scrolling startup display is long gone.5

That changes failure from a brief theatrical event into information one can inspect. A red message visible for a fraction of a second is an unusually demanding incident-reporting system.

A powerful manager acquires obligations

The design gave common startup and supervision work to a central manager. That could reduce repeated shell boilerplate and make dependencies easier to inspect. It also concentrated responsibility in a component whose correctness affects the entire machine.

There is a tradeoff in abstraction here. A script allows arbitrary local behavior; a declarative service file exposes a more regular model. Regularity is useful for tooling, but awkward cases still need somewhere to go. Compatibility with older service scripts helped migration without making all their behavior equivalent to native units.

The early experiment should also be kept separate from the later systemd collection. Its 2010 announcement put timers and fuller session-management work among future plans. Today’s journal, networking tools, and other associated components aren’t evidence of what version 0 shipped.1

A historical account that imports all those later features makes the original decision harder to understand. In April 2010, the central argument concerned dependency management, socket activation, and process supervision on Linux.

The enduring achievement is that “start these programs” became a request whose relationships could be represented, examined, and maintained. Faster boot was one possible result. A clearer explanation of why a service started, waited, or failed was another.

The machine still has to do the work. At least its services don’t all need to stand behind one another looking busy.

Sources

Footnotes

  1. Lennart Poettering, “Rethinking PID 1”, April 30, 2010. Experimental status, unit/dependency model, cgroups, Linux specificity, and future-work boundaries. ↩ ↩2 ↩3 ↩4

  2. Lennart Poettering, “systemd: The First Two Years”, FOSDEM 2013. Participant retrospective; early chronology and developer attribution. ↩

  3. Poettering, “systemd for Administrators, Part III”, October 1, 2010. Unit conversion, ordering versus activation, and ABRT readiness. ↩ ↩2

  4. Poettering, “systemd for Developers I”, May 18, 2011. Earlier inetd/launchd precedents, socket passing, queue behavior, and required service adaptation. The article’s catalogue example and timing values are original. ↩ ↩2

  5. Poettering, “systemd for Administrators, Part 1”, August 23, 2010. Retained runtime status; its prediction about Fedora 14 isn’t used as evidence of actual adoption. ↩

software-historylinuxsystemdoperating-systems2010s