LINUX-PRODUCTION Contents

Dependencies & Ordering (After/Wants/Requires)

Avoid boot deadlocks and brittle chains with correct dependency patterns.

On this page

Why Dependencies and Ordering Break Production

Most systemd problems are not “systemd is weird”. They are dependency modeling mistakes: services start in the wrong order, start before requirements are ready, or create circular dependencies. In production, your service should boot predictably every time.

Ordering vs Readiness: The #1 Misunderstanding

After= controls start order, not readiness. If you write:

After=network.target

It means: “start after systemd starts networking units”, not “the network is usable”. Your DNS might still be down, routes not ready, or network not online. This is why apps sometimes fail only on boot.

The Key Directives (Production Meaning)

After= and Before= (Ordering Only)

These specify ordering. They do not pull units in, and they do not guarantee readiness.

After=postgresql.service

Means: if both units are started, order them. It does not mean postgresql will start automatically unless you also add Wants/Requires.

Wants= (Soft Dependency)

Wants= pulls another unit in, but if it fails, your unit may still start. Good for optional dependencies.

Wants=network-online.target
After=network-online.target

Requires= (Hard Dependency)

Requires= says: if this dependency fails to start, my unit should fail too. Use for truly required services (database, critical mount).

Requires=postgresql.service
After=postgresql.service

Production rule: do not overuse Requires=. It increases boot fragility. Use it only when your service cannot function without the dependency.

BindsTo= (Tight Coupling)

BindsTo ties lifecycles strongly: if the dependency stops, your unit stops. Useful for mounts or devices, but dangerous if used carelessly.

PartOf= (Grouped Restarts/Stops)

PartOf helps propagate restarts/stops for operational grouping. Example: if you restart nginx, restart your app too.

PartOf=nginx.service

network.target vs network-online.target

network.target roughly means “network management is started”. network-online.target means “network is configured and considered online”. But it depends on your network manager and wait-online service.

Production pattern for network-dependent services:

Wants=network-online.target
After=network-online.target

Important: ensure the relevant wait-online service exists and is enabled:

  • systemd-networkd-wait-online.service
  • NetworkManager-wait-online.service

Readiness: Use Health Checks and Retries, Not Wishful Ordering

Even if ordering is correct, readiness may not be. DNS might fail, DB might be starting, migrations may be running. Production-safe approach:

  • Application should retry dependencies (DB, cache) with backoff
  • systemd can do simple restart-on-failure loops with backoff
  • Use explicit readiness probes (HTTP health checks) at higher layers

Common Dependency Patterns

Service Depends on Database (Typical)

[Unit]
Requires=postgresql.service
After=postgresql.service

But also: your app should still retry DB connection on boot. Do not rely solely on ordering.

Service Needs a Mount

If your app needs /srv mounted:

[Unit]
RequiresMountsFor=/srv/myapp

This is often safer than manual After=mount units.

Avoiding Circular Dependencies

Circular dependencies cause boot deadlocks or unpredictable ordering. Symptoms:

  • Units stuck in activating
  • Jobs canceled due to ordering cycle

Debug with:

systemd-analyze critical-chain
systemctl list-dependencies myapp
journalctl -b -u myapp --no-pager

Use systemd-analyze to See Real Boot Order

systemd-analyze blame | head -n 30
systemd-analyze critical-chain

This shows which units delay boot and which dependencies are in the chain.

Operational Reality: Don’t Make Boot Fragile

A production server must recover after reboot without humans. Over-modeling dependencies makes boot fragile. Prefer:

  • Minimal hard dependencies
  • Retries and backoff in application
  • Clear observability (logs show why dependency failed)

Common Production Mistakes

  • Assuming After= means “ready”
  • Using Requires= for optional components
  • Creating circular dependencies via PartOf/BindsTo misuse
  • Not enabling wait-online service but using network-online.target
  • Building boot success on perfect dependency timing (no retries)

Mental Model

systemd dependencies are about ordering and lifecycle. Readiness is a separate concept. Production robustness comes from: ordering where necessary + retries where reality is messy.

Production Checklist

  • Use After= for ordering only (do not confuse with readiness)
  • Use Wants= for soft dependencies, Requires= only for truly hard needs
  • For network: Wants+After network-online.target (and ensure wait-online exists)
  • Use RequiresMountsFor for filesystem needs
  • Run systemd-analyze critical-chain when boot behavior is weird
  • Ensure the app has retry/backoff for dependency readiness