Wants= is more of a polite suggestion, while Requires= is a hard dependency that will bring everything down with it.

Let’s see systemd in action. Imagine we have a simple web server that needs a database to be up and running before it starts. We can model this with systemd unit files.

First, our database service, let’s call it mydb.service:

[Unit]
Description=My Awesome Database

[Service]
ExecStart=/usr/local/bin/start-my-db
ExecStop=/usr/local/bin/stop-my-db
Type=forking

[Install]
WantedBy=multi-user.target

This is a pretty standard service file. It describes how to start and stop our database. The WantedBy=multi-user.target part means that when the system reaches the multi-user.target (the typical state for a server with networking and logins), this service could be started if it’s enabled.

Now, let’s create our web server service, mywebapp.service:

[Unit]
Description=My Awesome Web Application
Requires=mydb.service
After=mydb.service

[Service]
ExecStart=/usr/local/bin/start-my-webapp
ExecStop=/usr/local/bin/stop-my-webapp
Type=forking

[Install]
WantedBy=multi-user.target

Here’s where the magic happens.

  • Requires=mydb.service: This is the strong, unbreakable bond. If mydb.service fails to start or is stopped unexpectedly, mywebapp.service will also be stopped. It’s like saying, "I absolutely cannot run without mydb.service."
  • After=mydb.service: This is about ordering. It tells systemd that mywebapp.service should start after mydb.service has already started. It doesn’t guarantee mydb.service will start, only that if mywebapp.service is starting, mydb.service should have already been brought up.

So, if you were to enable and start mywebapp.service:

sudo systemctl enable mywebapp.service
sudo systemctl start mywebapp.service

systemd would first ensure mydb.service is started (because of Requires= and After=). If mydb.service starts successfully, then mywebapp.service will proceed to start. If mydb.service fails to start for any reason, mywebapp.service will not even attempt to start, and systemd will report mywebapp.service as failed because its requirement (mydb.service) is not met.

Now, let’s contrast this with Wants=. Imagine a less critical service, like a monitoring agent that prefers to have the database running but can function somewhat independently. Let’s create mymonitor.service:

[Unit]
Description=My Awesome Monitor
Wants=mydb.service
After=mydb.service

[Service]
ExecStart=/usr/local/bin/start-my-monitor
ExecStop=/usr/local/bin/stop-my-monitor
Type=forking

[Install]
WantedBy=multi-user.target

With Wants=mydb.service:

  • Wants=mydb.service: This is a weaker dependency. systemd will try to start mydb.service before starting mymonitor.service. However, if mydb.service fails to start, mymonitor.service will still attempt to start. It’s more of a "nice-to-have" relationship. The monitor might degrade gracefully if the database isn’t there, or it might just report errors.
  • After=mydb.service: This still dictates the startup order. mymonitor.service will wait for mydb.service to be active before it tries to start.

The key difference is the failure behavior. If mydb.service fails with Requires=, the dependent service also fails. If mydb.service fails with Wants=, the dependent service still tries to start.

The After= directive is crucial for defining the correct startup sequence. Without it, systemd might try to start mywebapp.service before mydb.service has finished initializing, even if Requires= is set. After= ensures that mydb.service is already active (or at least has completed its startup process) before mywebapp.service begins its own startup.

It’s also worth noting that Requires= implies Wants=. If you specify Requires=, you don’t necessarily need to specify Wants=mydb.service as well, because the stronger requirement already includes the weaker one. However, Wants= does not imply Requires=.

The WantedBy= directive in the [Install] section is what allows systemctl enable to create symbolic links in the appropriate .wants or .requires directories within the target unit’s configuration. For example, sudo systemctl enable mywebapp.service will create a symlink like /etc/systemd/system/multi-user.target.wants/mywebapp.service, telling systemd to start this service when multi-user.target is activated.

The most surprising implication of Requires= is that if the required service is stopped after the dependent service has started, the dependent service will also be stopped. This is a cascade effect designed to maintain service integrity. If your database goes down, you probably want your web app to go down with it, not keep trying to serve requests to a non-existent backend.

Understanding the subtle but critical distinction between Requires= and Wants=, and always pairing them with After= for proper ordering, is fundamental to building robust and predictable service dependencies in systemd.

The next logical step is exploring how Partof= and PropagatedStop= can further control service stop behavior.

Want structured learning?

Take the full Systemd course →