How to Speed Up Fedora Boot Time by Optimizing systemd Services

Disable unused systemd services like ModemManager or Bluetooth using systemctl to reduce Fedora boot time.

You upgraded to Fedora 41 and the boot drags

You upgraded to Fedora 41 and the boot sequence drags. The graphical login appears, but only after a long pause where the system seems stuck on the splash screen. You run systemd-analyze blame and see NetworkManager-wait-online.service taking 12 seconds. You suspect a service is waiting for something that never arrives. You want to cut the boot time without breaking your network or losing functionality.

systemd boot time depends on the critical path

systemd manages boot by starting units in parallel. The total boot time is usually determined by the longest chain of dependencies, not the sum of all services. If one service waits for a network connection that never arrives, every service depending on that network connection waits too. This creates a bottleneck.

Think of the boot process as a project with multiple tasks. Some tasks can happen at the same time. Others must wait for prerequisites. The project finishes when the longest chain of dependent tasks finishes. That chain is the critical path. Disabling a service that is not on the critical path does not reduce boot time. You must find the service on the critical path and remove or fix it.

systemd-analyze blame lists services by how long they took to start. This list helps you spot slow services, but it does not tell you if they are blocking the boot. A service can take 5 seconds to start but run in the background without delaying the login. systemd-analyze critical-chain shows the dependency path from the root to the target you are booting to. This command reveals the actual bottleneck.

Check the critical chain first. Disabling a service off the critical path wastes time.

Find the service slowing you down

Here's how to identify which services are slowing down the boot process and which dependency chain is the bottleneck.

# Show services sorted by startup time, longest first.
# Focus on user-space services, not kernel or initrd units.
systemd-analyze blame

# Show the dependency chain that determines the total boot time.
# The path ends at the target, usually graphical.target.
systemd-analyze critical-chain

Look at the output of systemd-analyze blame. Ignore the top few lines if they are kernel or initrd units. Those are harder to optimize and usually indicate hardware or kernel issues. Focus on user-space services like ModemManager.service, NetworkManager-wait-online.service, or bluetooth.service.

Now look at systemd-analyze critical-chain. The output shows a tree of dependencies. If graphical.target depends on multi-user.target, and multi-user.target depends on network-online.target, and network-online.target depends on NetworkManager-wait-online.service, you found the chain. The service at the bottom of the chain is holding up the boot. If that service takes 12 seconds, the boot takes at least 12 seconds longer than necessary.

Run systemd-analyze without arguments. See if the delay is in the kernel or userspace.

Disable services you do not need

Here's how to disable a service that isn't needed on your hardware, such as ModemManager on a desktop without a cellular modem.

# Remove the service from the default target symlinks so it does not start on boot.
# The --now flag stops the service immediately as well.
sudo systemctl disable --now ModemManager.service

Disabling a service removes it from the startup sequence. The service remains installed but does not start automatically. Use this for services that are unnecessary for your workflow.

Common candidates for disabling:

  • ModemManager.service: Probes for cellular modems. Disable if you have no modem.
  • bluetooth.service: Manages Bluetooth. Disable if you have no Bluetooth devices.
  • cups.service: Manages printing. Disable if you have no printers.
  • avahi-daemon.service: Provides mDNS discovery. Disable if you don't use AirPrint or local network discovery.
  • NetworkManager-wait-online.service: Waits for a full network connection. Disable if your desktop apps handle network availability asynchronously. This is safe for 99% of desktop users.

Disabling NetworkManager-wait-online.service is often the single biggest win. The service waits for network-online.target to be reached. On a wired connection, this is fast. On Wi-Fi, it can hang if the network is slow or unavailable. Most desktop applications do not need the network to be fully online before the login screen appears. They handle connection drops gracefully. Disabling this service allows the boot to proceed while the network connects in the background.

Reboot after disabling a service. The change only takes effect on the next boot.

Mask services that cause errors

Here's how to mask a service to prevent it from starting even if another service depends on it.

# Create a symlink to /dev/null to prevent the service from starting.
# This blocks the service even if another unit pulls it in via dependency.
sudo systemctl mask bluetooth.service

Masking is stronger than disabling. It creates a symlink from the unit file to /dev/null. systemd treats this as a permanent refusal to start the unit. Use masking when a service is broken, causes conflicts, or must never start even via dependency pull-in.

If bluetooth.service fails and blocks the boot, masking it removes the failure from the boot sequence. You can unmask the service later with sudo systemctl unmask bluetooth.service.

Masking is useful for services that are pulled in by other units but cause errors. For example, if a package depends on NetworkManager-wait-online.service and that service hangs, masking it prevents the hang. However, masking can break dependencies. If another service requires the masked service, that service will fail. Check systemctl status after masking to see if other units report dependency failures.

Unmask before you debug. Masking hides the service, making it harder to see why it failed.

Verify the improvement

Here's how to measure the new boot time and confirm the optimization took effect.

# Show the total boot time and breakdown by phase.
# Compare the userspace time with your previous measurement.
systemd-analyze

# Show the time taken by each service after the reboot.
# Verify that the disabled service no longer appears in the list.
systemd-analyze blame

Reboot the system. Run systemd-analyze to see the new total time. Compare the userspace time with the previous measurement. If the time dropped, the optimization worked. If the time stayed the same, the bottleneck moved. Check systemd-analyze critical-chain again to find the new bottleneck.

You can also check the previous boot log with journalctl -b -1. This shows logs from the boot before the current one. Compare the timestamps of service starts to see where the delay was.

Reboot before you debug. Half the time the symptom is gone after a clean boot cycle.

Common pitfalls and recovery

Disabling or masking essential services can break the boot. If you disable NetworkManager.service, the network will not start. If you disable systemd-logind.service, you cannot log in. If you disable graphical.target, the desktop will not start.

If you break the boot, you will see errors in the journal. The system may drop to an emergency shell or fail to start the display manager. Use the GRUB menu to boot into recovery mode. Select the kernel entry, press e to edit, and add rd.break to the kernel line. This drops you to a root shell where you can unmask or re-enable services.

Dependency failed for Network Manager Wait Online.

This error appears when NetworkManager-wait-online.service cannot start because NetworkManager.service failed. Fix the underlying service, don't just mask the waiter. Check journalctl -xe for details. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style to filter for a specific unit.

SELinux denials can look like service failures. If a service fails with a permission error, check journalctl -t setroubleshoot for SELinux alerts. Read the one-line summary before disabling SELinux. The denial often points to a misconfiguration that can be fixed without turning off security.

Trust the package manager. Manual file edits drift, snapshots stay. If you break the boot, use the recovery mode in GRUB to unmask the service.

When to use which approach

Use systemctl disable when the service is unnecessary for your hardware or workflow.

Use systemctl mask when the service is broken, causes conflicts, or must never start even via dependency.

Use systemd-analyze critical-chain when the total boot time is dominated by a single dependency path.

Use systemd-analyze blame when you suspect a specific service is slow but don't know which one.

Stay on the default configuration if the boot time is acceptable and you value stability over milliseconds.

Use dnf upgrade --refresh if the slowdown appeared after an update, as a package might have introduced a regression.

Run systemctl status first. Read the actual error before guessing.

Where to go next