The Pi-hole gravity database isn’t just a flat list of domains; it’s a carefully structured SQLite database optimized for rapid lookups, and its efficiency is the core reason Pi-hole can block so many domains without bogging down your network.
Let’s peek inside. Imagine you’ve just installed Pi-hole and added a few blocklists. When you run pihole -g, Pi-hole downloads these lists, cleans them up, and imports them into its internal SQLite database, typically located at /etc/pihole/gravity.db. This database isn’t just storing the domains you want to block; it’s also storing the domains you don’t want to block (your whitelisted domains) and even the upstream DNS servers Pi-hole uses.
Here’s a look at the database structure using the sqlite3 command-line tool. First, open the database:
sudo sqlite3 /etc/pihole/gravity.db
Once inside, you can see the tables:
.tables
You’ll see tables like domainlist, querytypes, status, and tld. The domainlist table is where the magic happens. Let’s examine its schema:
.schema domainlist
This will show you something like:
CREATE TABLE domainlist (
id INTEGER PRIMARY KEY AUTOINCREMENT,
domain TEXT NOT NULL UNIQUE,
type INTEGER NOT NULL DEFAULT 0,
enabled INTEGER NOT NULL DEFAULT 1,
date_added INTEGER NOT NULL
);
The domain column stores the actual domain name (e.g., doubleclick.net). The type column is crucial: 0 typically means it’s a blocked domain, and 1 usually signifies a whitelisted domain. The enabled column lets you toggle entries on and off without deleting them, and date_added tracks when the entry was imported.
Now, let’s see some actual data. If you have some domains blocked, you might see:
SELECT domain, type FROM domainlist WHERE type = 0 LIMIT 5;
This might output:
doubleclick.net|0
googleadservices.com|0
googlesyndication.com|0
adservice.google.com|0
google.com|0
And for your whitelisted domains:
SELECT domain, type FROM domainlist WHERE type = 1 LIMIT 5;
This could show:
pihole.net|1
gravity.pi-hole.net|1
discourse.pi-hole.net|1
github.com|1
reddit.com|1
When a DNS query comes into Pi-hole, it doesn’t scan through every single line of a text file. Instead, it performs a highly optimized lookup in this domainlist table. Because the domain column has a UNIQUE constraint and is indexed (SQLite automatically creates an index on unique columns and primary keys), the database can find whether a queried domain exists in the blocked list in milliseconds, even with millions of entries. This is vastly faster than searching through a plain text file.
The tld table is another interesting piece. It stores a list of top-level domains (like com, org, net). This helps Pi-hole distinguish between blocking example.com and blocking everything.example.com or even sub.sub.example.com. It’s a subtle but important optimization for how it handles wildcard blocking and domain matching.
The querytypes table, while less frequently modified by users, stores the DNS query types (A, AAAA, CNAME, etc.) that Pi-hole is configured to intercept and resolve. This allows Pi-hole to be granular about what kinds of DNS requests it processes and blocks.
The real power of the gravity database lies in its indexing and the SQLite engine’s ability to perform these lookups extremely quickly. When you run pihole -g, Pi-hole essentially rebuilds this optimized structure from your downloaded blocklists. It’s not just copying text; it’s compiling a highly efficient lookup index.
The type column in the domainlist table actually has more than just 0 and 1. While 0 is blocked and 1 is whitelisted, other values can represent different kinds of blocking or special handling, though these are less commonly manipulated directly by users and more often managed by Pi-hole’s internal logic or specific features like regex blocking.
After you’ve mastered the gravity database, you’ll likely want to explore how Pi-hole’s query logging and DNSSEC validation interact with this core blocking mechanism.