Postfix - Early Switching Away From bdb on Debian 13 Trixie
A few days ago, Wietse Venema (author of Postfix) sent an email to the Postfix users mailing list
entitled “Automatic migration to non-Berkeley DB” (2026-01-04). A discussion followed on the mailing list, and this triggered me to investigate how this would apply to my mail server - and, inevitably, I tried to re-configure my mail server without using bdb.
The gist: Berkeley DB has already been removed from some of the major Linux distributions. RedHat Enterprise Linux 10, for example, no longer provides bdb, and the version of Postfix on RHEL 10 is built without bdb support. Several smaller distributions have also already made the move. For the countless Postfix installations relying on hash: and btree: database types, this represents a fundamental infrastructure change that will inevitably be coming to all mail server administrators at some point.
Venema outlined an elegant solution for Postfix 3.11: an automatic emulation layer that would transparently migrate databases on-demand, re-indexing them in the background using modern alternatives like CDB or LMDB. The helper daemon would handle the transition seamlessly, with Postfix continuing to work even if administrators ignored the migration reminders.
My current configuration
Of course, having been made aware of this, I had to have a look at whether/where my mail server uses hash: and/or btree:.
# postconf | grep -E '(hash:|btree:)'
address_verify_map = btree:${data_directory}/verify_cache
alias_database = hash:/etc/aliases
alias_maps = hash:/etc/aliases
postscreen_cache_map = btree:${data_directory}/postscreen_cache
postscreen_dnsbl_reply_map = texthash:/etc/postfix/dnsbl_reply
smtp_tls_session_cache_database = btree:${data_directory}/smtp_tls_session_cache
smtpd_sender_login_maps = hash:/etc/postfix/sender_login_maps $virtual_alias_maps
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_tls_session_cache
transport_maps = hash:/etc/postfix/transportThe question then arises which database to use instead of bdb. On the same mailing list, I found two recent discussions on this topic, in which cdb
was mentioned, as well as lmdb
. Since I am not familiar with either one, I searched online. This basically boiled down to:
LMDB offers superior performance for concurrent, high-write, large-scale scenarios; CDB excels at simple, static lookups.
So, what kind of database usage do I have on my mail server?
From the above postconf output, I can see that there are a couple of static databases (e.g. aliases; updated by me once during server configuration), as well as databases that are updated frequently, incrementally (by Postfix), like the one for postscreen.
For the first set of databases, cdb would be ideal. For the second set, lmdb would be required.
Could I just go with lmdb and call it a day? Definetally! I run a tiny mail server for myself and a few. I doubt using cdb would be measurable.
Still, if I had a larger server, I could configure things as follows (based on the above postconf output):
| What | Original db type | Static OR Incremental | Purpose | New db type |
|---|---|---|---|---|
| address_verify_map | btree | Incremental | Caches expensive recipient verification probes | lmdb |
| alias_database | hash | Static | Local email aliases (e.g., root → admin) | cdb |
| alias_maps | hash | Static | Local email aliases lookup | cdb |
| postscreen_cache_map | btree | Incremental | Tracks clients that passed/failed postscreen tests | lmdb |
| smtp_tls_session_cache_database | btree | Incremental | Caches outbound TLS session parameters | lmdb |
| smtpd_sender_login_maps | hash | Static | Maps sender addresses to SASL login names for auth | cdb |
| smtpd_tls_session_cache_database | btree | Incremental | Caches inbound TLS session parameters | lmdb |
| transport_maps | hash | Static | Routes mail to specific transports/destinations | cdb |
This would then result in the following configuration in /etc/postfix/main.cf (the location of main.cf may be different on your server).
# postconf | grep -E '(hash:|btree:|cdb:|lmdb:)'
address_verify_map = lmdb:${data_directory}/verify_cache
alias_database = cdb:/etc/aliases
alias_maps = cdb:/etc/aliases
postscreen_cache_map = lmdb:${data_directory}/postscreen_cache
postscreen_dnsbl_reply_map = texthash:/etc/postfix/dnsbl_reply
smtp_tls_session_cache_database = lmdb:${data_directory}/smtp_tls_session_cache
smtpd_sender_login_maps = cdb:/etc/postfix/sender_login_maps $virtual_alias_maps
smtpd_tls_session_cache_database = lmdb:${data_directory}/smtpd_tls_session_cache
transport_maps = cdb:/etc/postfix/transportTip
Debian splits Postfix database support into separate packages. You’ll need to install postfix-cdb and postfix-lmdb before proceeding, or Postfix won’t recognise your new database types.
The smtp_tls_session_cache_database and smtpd_tls_session_cache_database are seemingly not really necessary on a small server with little traffic, according to a post
by Viktor Dukhovni to the postfix-users mailing list today. So, as I am making the above changes, I am actually commenting out those two databases. I don’t expect I will notice a difference.
Migration Process
The migration involves three steps: converting the databases, updating the configuration, and cleaning up.
Step 1: Convert static databases to CDB
For static lookup tables, use postmap (or postalias for /etc/aliases):
postalias cdb:/etc/aliases
postmap cdb:/etc/postfix/sender_login_maps
postmap cdb:/etc/postfix/transportThis creates .cdb files alongside your existing .db files.
Step 2: Update main.cf
Edit /etc/postfix/main.cf and change all hash: references to cdb: for static tables, and btree: to lmdb: for dynamic caches (as shown in the table above).
Step 3: Restart and clean up
postfix stop
# Remove old BDB cache files
rm /var/lib/postfix/postscreen_cache.db
rm /var/lib/postfix/verify_cache.db
rm /var/lib/postfix/smtp_tls_session_cache.db
rm /var/lib/postfix/smtpd_tls_session_cache.db
postfix startStep 4: Test everything works For the below tests, change the values in italics to something that works for you. For example, look up what you have got in your transport map, and use a corresponding value.
# Test static lookups
postalias -q _root_ cdb:/etc/aliases
postmap -q _gmail.com_ cdb:/etc/postfix/transport
# Send test email
echo "Migration test" | mail -s "Test" _your@email.address_
# Watch logs
tail -f /var/log/mail.logStep 5: Clean up old BDB files (after confirming everything works)
rm /etc/aliases.db
rm /etc/postfix/sender_login_maps.db
rm /etc/postfix/transport.dbWhy Migrate Now?
While Postfix 3.11 will handle this migration automatically, there are good reasons to migrate proactively:
- Control the timing - Migrate during a maintenance window, not when your distribution forces it
- Optimize while you’re at it - Use CDB for static data, LMDB for dynamic (or just LMDB for everything on small servers)
- Reduce future surprises - One less thing to worry about when upgrading
For my small mail server, the entire migration took about 15 minutes, including testing. The server has been running smoothly since, with zero Berkeley DB dependencies.
When major distributions inevitably remove Berkeley DB support from their Postfix packages, I’ll already be ahead of the curve. And if you’re reading this, you can be too.