skip to content

On Fedora 41 and later the `dnf` command is DNF 5, while RHEL 9 still ships dnf 4. What changes for you as an operator, and what is most likely to break?

level: middleimportance: nice to knowfreq 24%

answer

  1. same command, new engine
  2. Fedora 41 flipped the default
  3. libdnf5 underneath
  4. plugins and the Python API are the risk
  5. stop parsing human-readable output

basics

~20 s

DNF 5 is a rewritten implementation on the libdnf5 stack, made the default dnf in Fedora 41. Everyday verbs and the .repo files are broadly unchanged; what breaks is automation built on dnf 4's Python API, its plugins, or its exact output format.

solid answer

~50 s

DNF 5 is a rewrite rather than a new release line: the resolution and repository handling moved into a single native `libdnf5` stack, and Fedora 41 made `dnf5` the command you get when you type `dnf`. RHEL 9 is still on dnf 4, so for now you are operating both. Day to day the surface is deliberately familiar — `install`, `upgrade`, `remove`, `repoquery`, `history` all work, configuration is still `/etc/dnf/dnf.conf`, and repository definitions still live in `/etc/yum.repos.d/`. It is also what fills the minimal-container niche `microdnf` used to. The breakage is in the layer around it: plugins written for dnf 4 and scripts importing dnf 4's Python API do not carry over unchanged, and anything parsing dnf's human-readable output is exposed because the formatting differs. So when I move a fleet, I check plugin availability first and stop scraping output.

go deeper

for a junior

Know that Fedora 41 and later ship DNF 5 as the dnf command while RHEL 9 uses dnf 4, and that the everyday commands you type are the same on both.

for a middle

Explain that DNF 5 is a re-implementation on libdnf5 rather than an incremental release, and name what carries over unchanged — config, repo files, the RPM database — versus what does not.

for a senior

Frame it as a migration you would run: audit plugin dependencies and Python-API use, retest the unattended update path, and eliminate output parsing rather than patching it release by release.

for a principal

Own the exposure: decide how much of your fleet automation is allowed to depend on a specific package-manager implementation at all, and push toward interfaces that survive a tool rewrite across a mixed RHEL and Fedora estate.

## What DNF 5 actually is DNF 5 is not dnf 4 with more features; it is a re-implementation. Where dnf 4 was a Python program sitting on the `libdnf` and `hawkey` libraries, DNF 5 consolidates the work into a single native `libdnf5` stack with the command-line client built directly on it. The motivations were the ones you would expect from a package manager that runs on everything from a laptop to a minimal container image: less memory, faster metadata handling, one library that other tools can link against instead of several, and a story for the tiny-container case that previously required a separate cut-down tool, `microdnf`. Fedora 41 made it the default: on that release and later, `dnf` gives you DNF 5. RHEL 9 and earlier remain on dnf 4. If you operate a mixed estate, that is the practical situation you are in — the same command name driving two implementations. ## What stays the same Deliberately, most of what you type. The everyday verbs — `install`, `remove`, `upgrade`, `search`, `info`, `repoquery`, `history` — are there and mean the same things. Configuration remains `/etc/dnf/dnf.conf`, repository definitions remain `.repo` files under `/etc/yum.repos.d/` with the same keys, and the local RPM database underneath is unchanged. Transaction history is still recorded and still queryable. A person who knows dnf 4 is productive on DNF 5 within minutes, which is exactly the design goal for a tool this central. ## What breaks Three categories, in rough order of how often they bite. **Plugins.** dnf 4's plugin ecosystem is Python code against dnf 4's internals. DNF 5 has its own plugin mechanism, and a plugin only exists there if someone ported or rewrote it. Before migrating anything that depends on a plugin, check that the DNF 5 equivalent is packaged for the release you are moving to — this is the concrete pre-flight check, not a theoretical concern. **Scripts using the Python API.** Anything that does `import dnf` and drives transactions programmatically is written against dnf 4's API. libdnf5 exposes its own bindings; the code does not port by changing an import line. If you have such automation, it is a rewrite, and the cheaper answer is usually to stop using the API and shell out to the CLI with machine-readable options. **Output parsing.** Any script that greps or awks dnf's human-readable output is fragile across the change, because formatting is not a contract. This is a good moment to fix it properly: use exit statuses, use `repoquery` with a format option rather than parsing a table, and let a package-management module in your configuration-management tool do the work where one exists. ## The operator's checklist When a release flips you to DNF 5, the review worth doing is short. List the dnf plugins your automation relies on and confirm each has a DNF 5 counterpart. Grep your repositories for `import dnf` and for pipelines that parse dnf output. Re-test your unattended-update path end to end rather than assuming it survived. Confirm your `.repo` files are still doing what you expect with `dnf repolist --all`. None of that is difficult; skipping it is how a fleet discovers the change during a patch window instead of during a migration. ## Why an interviewer asks It is a low-frequency question and nobody will fail an interview for not knowing the version numbers. What it does probe usefully is whether you think about tooling migrations the way an operator should: not "do the commands still work" but "what did I build on top of this tool that assumed more than the command names". The candidate who immediately says "the CLI is fine; my scripts that parse its output and my plugins are the risk" has answered the question that was actually being asked.

  • If your automation must work on both a dnf 4 and a DNF 5 host, how would you write it?
    Drive the CLI rather than the Python API, since the verbs are common to both, and depend on exit statuses instead of parsed output. Avoid plugin-specific commands unless you have confirmed the plugin exists on both. Better still, use a configuration-management package module that abstracts the difference, and keep any version-specific handling in one place rather than scattered through scripts.
  • What niche did `microdnf` fill, and how does DNF 5 change that?
    `microdnf` was a stripped-down client for container images where installing the full Python dnf stack cost more than the packages you wanted. DNF 5's native implementation is small enough to serve that case itself, so the minimal-container role folds back into the main tool instead of needing a separate command with a reduced feature set. One fewer thing whose flags differ from the tool you use on real hosts.

saying these in an interview costs you the question

  • Assuming DNF 5 is just a newer dnf 4 release
  • Expecting dnf 4 plugins to load unchanged
  • Porting `import dnf` scripts by editing the import
  • Grepping dnf output and calling it an interface
  • Believing repo files or dnf.conf must be rewritten

context