The scenario
You run sudo dnf upgrade on a Fedora workstation and watch the dependency resolver crawl for forty seconds. The terminal prints a wall of package names, calculates conflicts, and finally asks if you want to proceed. You hit enter, and the download starts. A week later, you read about DNF5. It promises a C++ rewrite, instant resolution, and a cleaner plugin system. You want the speed, but you also run a system that hosts a local development server and a few custom automation scripts. Breaking the package manager is not an option. You need to know what actually changes, how to test it without locking yourself out, and when the rewrite is ready for daily work.
What DNF5 actually changes
DNF5 is not a patched version of DNF4. It is a ground-up rewrite in C++. The original DNF4 runs on Python. Python plugins load slowly, and the dependency resolver has to serialize transactions through a language that was never designed for heavy concurrent parsing. DNF5 moves the core engine to C++. It keeps the same repository metadata format, the same transaction history database, and the same command-line syntax. The difference is under the hood. The resolver now runs in compiled code. It parses package metadata in parallel. It drops the old Python plugin loader and replaces it with a modular C++ plugin architecture that initializes in milliseconds.
Think of DNF4 like a restaurant kitchen where every order passes through a single head chef who reads recipes in a foreign language. DNF5 gives the kitchen multiple stations, pre-translated recipe cards, and a direct line to the walk-in fridge. The meals come out faster. The inventory system stays the same. You still order the same dishes.
The rewrite also standardizes the API. DNF4 exposed a Python API that third-party tools had to wrap. DNF5 exposes a clean C++ API with a stable ABI. Future GUI frontends and automation scripts will bind directly to the core instead of shelling out to a Python interpreter. This matters for container builds, CI pipelines, and any environment where package management happens in a loop. The resolver uses a modern SAT solver that evaluates constraints concurrently. It skips redundant metadata scans and caches dependency graphs in memory. Large repository sets that used to trigger swap thrashing now resolve in under two seconds.
Run the resolver on a clean cache first. You will feel the difference immediately.
How to run DNF5 safely
Fedora ships DNF5 alongside DNF4 during the transition period. The dnf command still points to the Python version by default. You can invoke the new engine explicitly without touching system symlinks. Run the dnf5 binary directly. It reads the same repository configuration, respects the same exclude lists, and writes to the same transaction history.
Here is how to check whether DNF5 is already installed on your system.
rpm -q dnf5
# Confirms the package is present and shows the exact version string
# Returns "package dnf5 is not installed" if your release predates the transition
# Use this before attempting any alias or symlink changes
Once confirmed, run a dry-run update to watch the new resolver in action. The dry-run flag prevents any package downloads or filesystem changes.
sudo dnf5 update --downloadonly --assumeno
# --downloadonly fetches packages without triggering the rpm transaction
# --assumeno automatically answers no to the final prompt
# Lets you measure resolver speed without altering the system state
If the output looks correct and the timing feels faster, run a real update. The command syntax matches DNF4 exactly.
sudo dnf5 upgrade --refresh
# --refresh forces a metadata pull before resolving dependencies
# Keeps your local cache aligned with the remote repository
# Standard weekly maintenance practice on Fedora systems
To make dnf5 your default for interactive sessions, add a shell alias. This changes nothing at the system level. Scripts and cron jobs will still call the binary explicitly or use the unaliased dnf path.
echo 'alias dnf="dnf5"' >> ~/.bashrc
# Appends the alias to your interactive shell configuration
# Only affects new terminal sessions for your user account
source ~/.bashrc
# Reloads the current shell so the alias takes effect immediately
System-wide switching requires changing the symlink in /usr/bin/dnf. Fedora does not recommend this yet. The symlink points to a wrapper script that handles legacy compatibility flags. Overwriting it breaks third-party tools that expect the Python interpreter path. Stick to the explicit dnf5 binary or the user alias until the release team flips the default.
Test the alias in a separate terminal before closing your current session. A broken alias leaves you guessing which engine ran the last command.
Verify the switch worked
Run a transaction history query to confirm DNF5 recorded the operation. The history database lives at /var/lib/dnf/history.sqlite. Both versions read and write to the same file.
Here is how to inspect the last transaction and confirm the new engine logged it correctly.
dnf5 history list
# Queries the shared SQLite database for completed transactions
# Shows the command line, package count, and timestamp for each run
dnf5 history info 1
# Replaces 1 with the actual ID from the previous output
# Displays the exact packages installed, updated, or removed
Check the plugin status to see which extensions loaded. DNF5 reports active plugins at the top of every verbose run.
Here is how to capture the initialization block without scrolling through hundreds of package lines.
dnf5 update -v 2>&1 | head -20
# -v enables verbose output to show resolver and plugin initialization
# 2>&1 redirects stderr to stdout so head captures the full header
# head -20 limits the output to the initialization block
Look for lines starting with Plugin: in the output. If a plugin you rely on does not appear, it has not been ported to the C++ architecture yet. The resolver will still work. The missing plugin just won't run.
Read the history before you troubleshoot. The transaction log tells you exactly what changed and when.
Common pitfalls and missing plugins
The biggest friction point during the transition is plugin compatibility. DNF4 plugins are written in Python. DNF5 plugins are compiled C++ shared libraries. The Fedora maintainers are porting the core plugins gradually. You will see gaps.
The dnf-automatic plugin, which handles unattended security updates, has a DNF5 equivalent but uses a different configuration path. The old config lives in /etc/dnf/automatic.conf. The new config lives in /etc/dnf5/automatic.conf. If you migrate to DNF5 for daily use, you must update the timer and the config file. Otherwise, your unattended updates will silently stop.
# /etc/dnf5/automatic.conf
[commands]
upgrade_type = default
# Controls whether updates replace packages normally or skip obsoletes
apply_updates = yes
# Enables automatic installation after resolution
download_updates = yes
# Fetches packages to the cache before applying them
Another common trap is the --setopt flag. DNF4 accepted arbitrary key-value pairs that bypassed config files. DNF5 validates these strictly. Passing an unknown option triggers a hard failure instead of a silent ignore. You will see this exact error if you copy an old script:
Error: Unknown configuration option 'install_weak_deps' in command line.
The resolver refuses to start when it encounters an invalid directive. Check the man page for the exact flag name. DNF5 renamed a few legacy options to align with the new API.
Repository metadata caching also behaves differently. DNF4 cached metadata in /var/cache/dnf/. DNF5 uses /var/cache/dnf5/. Both directories exist side by side. Running dnf5 clean all only clears the DNF5 cache. It leaves the DNF4 cache untouched. If you switch back and forth, you will accumulate duplicate metadata. Run the clean command for whichever engine you are actively using.
SELinux contexts remain identical. The package manager binaries run under the same domain. You will not see AVC denials from switching to DNF5. If you do encounter a denial, check journalctl -t setroubleshoot for the one-line summary. Read the suggested fix before touching setenforce. Manual policy edits drift. Snapshots stay.
Config files in /etc/ are user-modified. Files in /usr/lib/ ship with the package. Edit /etc/. Never edit /usr/lib/. DNF5 follows this rule strictly. Overriding a shipped config in /usr/lib/ will be overwritten on the next package update. Keep your customizations in /etc/ and let the package manager handle the rest.
Run dnf5 plugins list before you automate. Missing plugins break scripts silently.
When to stick with DNF4 vs switch to DNF5
Use DNF4 when you rely on Python plugins that have not been ported yet. Use DNF4 when you run legacy automation scripts that depend on the Python API or specific wrapper behavior. Use DNF5 when you want faster dependency resolution on large systems with hundreds of enabled repositories. Use DNF5 when you are building containers or CI pipelines that run package operations in tight loops. Use DNF5 when you want to test the future default before Fedora flips the symlink. Stay on the explicit dnf5 binary for daily work until the release notes declare it stable for your version.
Keep the alias in your shell config. Drop it when the official release notes switch the default.