Two separate questions trip people up: ordering (who starts first) and requirement (must the other unit be running at all). systemd uses different directives for each.
Ordering vs. requirement
[Unit]
Description=My API
# Ordering: start this AFTER postgresql is up:
After=postgresql.service
# Requirement: pull postgresql in, and fail/stop if it fails:
Requires=postgresql.service
After=/Before=— ordering only. They say nothing about whether the other unit is even enabled.Wants=— a soft dependency: start the other unit too, but keep going if it fails. The most common, safest choice.Requires=— a hard dependency: if the required unit fails to start, this unit is not started. (Still addAfter=—Requires=alone doesn’t order.)BindsTo=— likeRequires=, but also stops this unit if the other one later stops.
Rule of thumb: pair an ordering directive (After=) with a requirement directive (Wants= or Requires=). They are independent.
Waiting for the network correctly
[Unit]
After=network-online.target
Wants=network-online.target
network.targetonly means networking is configured, not that an interface has an address. For “I need to reach the internet / a remote host”, usenetwork-online.target— and you mustWants=it (it isn’t pulled in by default). Enable the backing service once:
sudo systemctl enable systemd-networkd-wait-online.service # systemd-networkd
# or, on NetworkManager:
sudo systemctl enable NetworkManager-wait-online.service
Apply
sudo systemctl daemon-reload
sudo systemctl restart myapi.service
# See what it actually waited for:
systemctl list-dependencies myapi.service
Gotchas: ordering directives reference the dependency’s start-up; on shutdown the order is reversed automatically. Don’t over-use Requires= — a single flaky dependency can block your whole service. For “start mine, and if it dies take the helper with it”, that’s BindsTo= + After=.