In a systemd unit file, what is the difference between Wants=, Requires= and BindsTo=, and what happens to your service in each case when the unit it points at fails to start or stops later?
answer
- three strengths, one axis, no ordering
- does a failure take me down?
- explicit stop versus any stop
- devices and mounts want the strictest one
basics
~20 sWants= starts the other unit but tolerates its failure. Requires= makes your unit fail to start alongside it and stop when it is explicitly stopped. BindsTo= is stricter still: your unit stops whenever the bound unit stops for any reason, including a crash.
solid answer
~50 sAll three are *requirement* dependencies in the `[Unit]` section, and none of them imply ordering. `Wants=` is the weak one: systemd pulls the other unit in, but if it fails, your unit starts anyway — this is what `WantedBy=` in `[Install]` produces as a `.wants/` symlink. `Requires=` is strong: if the required unit fails to activate *and* you also have `After=` on it, your unit is not started, and if the required unit is later explicitly stopped, yours is stopped too. `BindsTo=` is `Requires=` plus one extra rule: your unit is stopped whenever the bound unit enters an inactive state for *any* reason — an unexpected exit, a device vanishing — not only a deliberate `systemctl stop`. The house rule is to use `Wants=` by default and reserve the strong forms for things your service genuinely cannot exist without.
go deeper
Know that these lines live in the [Unit] section and that Wants= is the forgiving one while Requires= is not. Being able to say "Wants= tolerates failure, Requires= does not" is enough at this level.
Explain the propagation rules precisely: which failure prevents a start, which stop propagates, and that BindsTo= also reacts to an unexpected exit. Say out loud that none of them imply ordering.
Show the operational judgment — that Requires= turns one broken unit into a cascade, that Wants= is the sane default on a fleet, and that you verify effective dependencies with systemctl show or list-dependencies rather than reading the file.
Own the failure-domain argument: how strong dependencies couple services into a single blast radius, when a hard coupling is the honest model (a mount, a device) and when the dependency really belongs in the application as a retry loop.
## Two independent axes systemd deliberately splits dependency into two orthogonal questions: 1. **Requirement** — should the other unit be pulled into this transaction, and what happens to me if it fails or goes away? That is `Wants=`, `Requires=`, `BindsTo=`, `Requisite=`, `PartOf=`, `Conflicts=`. 2. **Ordering** — who is allowed to run first? That is `After=` and `Before=`, and nothing else. Everything in this answer lives on axis 1. None of these directives orders anything, which is the single most common misconception about them. All of them go in the `[Unit]` section and all take a space-separated list of unit names, so they can be repeated or listed on one line. ## Wants= — the weak reference ```ini [Unit] Description=Report collector Wants=redis.service After=redis.service ``` Starting the collector queues a start job for `redis.service` as well. If Redis fails to start, or is not installed, or is stopped an hour later, the collector is unaffected. It is a best-effort "please also bring this up". This is the same mechanism the enable machinery uses: `WantedBy=multi-user.target` in `[Install]` creates a symlink in `multi-user.target.wants/`, and a symlink in a `.wants/` directory is exactly equivalent to a `Wants=` line in the target. That is why almost every enabled service on a running host is a *wanted* unit — a single failing daemon must not prevent the machine from reaching its boot target. **Default to `Wants=`.** It is the recommended strength in the systemd documentation precisely because it degrades gracefully. ## Requires= — the strong reference ```ini [Unit] Requires=postgresql.service After=postgresql.service ``` Two behaviours are attached: - **Activation failure.** If `postgresql.service` fails to activate *and* an `After=` ordering on it is present, your unit is not started. Without the `After=`, the two are started in parallel, so yours can already be running by the time the failure is reported — the requirement then does not save you. This is why `Requires=` and `After=` are nearly always written as a pair. - **Propagated stop.** If someone runs `systemctl stop postgresql.service`, your unit is stopped along with it. Note the wording: an *explicit* stop. If the PostgreSQL process merely crashes, `Requires=` alone does not take your unit down. ## BindsTo= — follows the other unit's life `BindsTo=` is `Requires=` plus: your unit is stopped whenever the bound unit stops for *any* reason, including an unexpected exit of its main process or the unit's underlying object disappearing. The canonical use is a non-service unit that can vanish outside anyone's control: ```ini [Unit] Description=Serial gateway BindsTo=dev-ttyUSB0.device After=dev-ttyUSB0.device ``` Unplug the adapter, the device unit goes away, and the gateway is stopped rather than left spinning on a file descriptor that will never come back. The same pattern applies to `.mount` units for a service that must not run without its storage. ## The neighbouring directives worth knowing - **`Requisite=`** — like `Requires=`, but it will *not* start the other unit. If it is not already active, your unit fails immediately. Use it as an assertion rather than a dependency. - **`PartOf=`** — one-directional propagation: when the listed unit is stopped or restarted, the same action is applied to yours, but not the reverse, and a failure is not propagated. This is the grouping directive. - **`Upholds=`** — a `Wants=` that is continuously re-asserted, so the other unit is restarted whenever it stops. Available in newer systemd versions. - **`Conflicts=`** — the negative dependency: starting your unit stops the conflicting one. It carries no ordering either, so pair it with `Before=`/`After=` or the stop and the start race. ## Implicit dependencies you did not write With `DefaultDependencies=yes` (the default), a normal service silently gains `Requires=sysinit.target`, `After=sysinit.target basic.target`, plus `Conflicts=shutdown.target` and `Before=shutdown.target`. That is why an ordinary unit does not need to say anything to be started after early boot and stopped cleanly at shutdown, and why an early-boot unit usually has to set `DefaultDependencies=no` to escape them. ## Inspecting what is actually in effect Don't reason from the file alone — drop-ins under `/etc/systemd/system/<unit>.d/*.conf` and `.wants/`/`.requires/` symlink directories add dependencies the file never mentions: ```bash systemctl show -p Wants -p Requires -p BindsTo -p After myapp.service systemctl list-dependencies myapp.service systemctl cat myapp.service ``` `systemctl cat` prints the effective unit including drop-ins; `systemctl show` prints the resolved property values, which is the truth systemd is actually working from. ## Choosing in practice Ask what should happen when the other thing is broken. If your service can start, log a warning and retry — `Wants=`. If starting it without the dependency produces a corrupt or misleading state — `Requires=` with `After=`. If the dependency is a physical resource that can disappear underneath you — `BindsTo=`. Over-using `Requires=` is a real availability hazard: it converts one failed unit into a chain of failed units, and at boot it can stop the host from reaching its target at all.
- When would you reach for Requisite= instead of Requires=?When the other unit must already be running and you do not want to start it yourself. `Requisite=` checks the state and fails your unit immediately if the named unit is not active, so it behaves as an assertion rather than an activation request. It is useful for units that should only run inside an already-established environment, where silently starting the missing piece would hide a real ordering mistake.
- How is Conflicts= different from these, and what is its classic trap?`Conflicts=` is the negative requirement dependency: starting your unit queues a stop for the conflicting one, and it applies in both directions. The trap is that, like the positive forms, it implies no ordering — so without a matching `Before=` or `After=` the stop of the old unit and the start of the new one are scheduled concurrently and can overlap on a port or a lock file.
- Why is a symlink in multi-user.target.wants equivalent to a Wants= line?systemd reads `.wants/` and `.requires/` directories next to a unit and treats each symlink inside them as a `Wants=` or `Requires=` entry on the owning unit. That is how enabling works without ever editing the target's file, and it means the dependency graph on a live host is the union of the unit files, their drop-ins and these symlink directories — which is why `systemctl show` is the reliable way to read it.
saying these in an interview costs you the question
- Says Wants= guarantees the dependency actually started
- Thinks Requires= also orders the two units
- Treats BindsTo= as just a synonym for Requires=
- Uses Requires= everywhere, so one failure cascades through boot
- Claims a crashing Requires= dependency always stops the dependent unit