Engineering · Privacy Architecture
Why We Chose SQLite for a Privacy-First URL Shortener (And Why It's a Perfect Fit)
When people think about building a URL shortener, the database conversation usually starts and ends with PostgreSQL, MySQL, or — if you're feeling trendy — some managed cloud database. At TraceNull, we went a different direction: SQLite.
It wasn't a compromise. It wasn't a "we'll migrate later" decision. SQLite is a deliberate, privacy-aligned architectural choice — and after running it in production, we're more convinced than ever that it's the right one.
Here's why SQLite and privacy-first services are a natural match, and what we learned building TraceNull's entire backend on top of it.
The Privacy Problem with Traditional Database Architectures
Most URL shorteners use a client-server database like PostgreSQL or MySQL. That means the database runs as a separate networked service — often on a different machine, sometimes in a different data center, frequently managed by a third party.
Every hop in that chain introduces privacy risk:
- Network exposure: Data travels over TCP connections that can be intercepted, logged, or monitored at the infrastructure level.
- Third-party access: Managed database providers (AWS RDS, PlanetScale, Supabase) have physical and logical access to your data. Their privacy policies apply too — not just yours.
- Telemetry and logging: Many managed services collect query logs, performance metrics, and connection metadata by default. That metadata can contain user information.
- Backup sprawl: Automated backups replicate your data across regions and retention periods you may not fully control.
Key principle: Every additional service that touches user data is a surface you must audit, secure, and include in your privacy policy. Fewer services means fewer risks.
For a service like TraceNull — where the entire value proposition is not tracking people — minimizing the number of systems that even could see user data isn't just good engineering. It's a privacy obligation.
What Makes SQLite Different
SQLite is an embedded database. It doesn't run as a separate process. It doesn't listen on a network port. It's a single file on disk, accessed directly by your application through a C library (or in our case, through Node.js bindings).
This architecture eliminates entire categories of privacy risk:
| Risk | Client-Server DB | SQLite |
|---|---|---|
| Network transmission of queries/data | Yes — over TCP/TLS | No — local file I/O only |
| Third-party infrastructure access | Often (managed DB providers) | No — runs on your server |
| Separate authentication surface | Yes — DB credentials, connection strings | No — filesystem permissions only |
| Query logging by external service | Common default | Not applicable |
| Backup replication to unknown regions | Depends on provider | You control all copies |
| Data residency compliance complexity | High | Low — data stays where the file is |
In short: with SQLite, your data never leaves your process unless you explicitly move it. For a GDPR-compliant service, that's an enormous simplification.
How TraceNull Uses SQLite in Production
Our stack is straightforward: Node.js + Express + SQLite + Caddy. Here's how SQLite fits into the architecture:
Short Link Storage
Every shortened URL — slug, destination, creation time, TTL, plan tier — lives in a single SQLite table. Lookups by slug are indexed and typically complete in under 1ms. For a URL shortener, read performance is everything, and SQLite's read speed on indexed lookups is exceptional because there's zero network overhead.
Aggregate Analytics (Not User Tracking)
When someone clicks a TraceNull short link, we increment a counter. That's it. No IP address, no user agent, no fingerprint, no cookie. Just a number going up.
SQLite handles this with a simple UPDATE ... SET clicks = clicks + 1 statement. Our admin dashboard — which shows redirect counts for today, 7 days, monthly, and yearly windows — queries these aggregates directly. As we covered in our admin dashboard article, the entire analytics system is built around counting events, not identifying people.
TTL Enforcement
Free-tier links expire after 2 hours, Pro links after 90 days, Business links after 365 days. A periodic cleanup task runs a single query:
When a link is deleted, it's gone. Not soft-deleted, not archived, not moved to cold storage. The row is removed from the file. After a VACUUM, the disk space is reclaimed. This is genuine data minimization — not just a policy, but a physical reality.
Watch out: Many "privacy-first" services claim data deletion but use soft deletes or delayed purges. With SQLite, you can verify deletion by inspecting the actual database file. Transparency you can audit.
"But Does SQLite Scale?"
This is the question every engineer asks, and it's a fair one. The honest answer: SQLite scales far beyond what most people assume, and well beyond what a URL shortener needs.
- Read throughput: SQLite can handle hundreds of thousands of reads per second on modern hardware. A URL shortener is overwhelmingly read-heavy (redirects vastly outnumber link creations).
- Write throughput: With WAL (Write-Ahead Logging) mode enabled, SQLite handles concurrent reads during writes gracefully. We enable this with
PRAGMA journal_mode=WAL;at startup. - Database size: SQLite comfortably handles databases up to several hundred gigabytes. A short link record is roughly 200 bytes. You'd need half a billion links to hit 100GB.
- Concurrency: SQLite supports multiple concurrent readers and a single writer. For a URL shortener where 99%+ of operations are reads (redirects), this is rarely a bottleneck.
Could TraceNull eventually outgrow SQLite? In theory, yes — if we reached tens of thousands of simultaneous write operations per second. In practice, we'd need to be processing more short link creations per second than Bitly does globally. We'll cross that bridge if we get there, and even then, we'd likely shard across multiple SQLite files before reaching for a networked database.
The Operational Benefits Privacy Engineers Love
Beyond the privacy advantages, SQLite brings operational simplicity that directly supports a privacy-first mission:
Single-file backups. Backing up the database means copying one file. You know exactly where your data is, on which disk, in which jurisdiction. GDPR Article 17 (Right to Erasure) becomes trivially auditable.
No credentials to leak. There's no database password, no connection string, no API key. The attack surface for data exfiltration shrinks to filesystem access — which your OS already protects.
No dependency on external services. If a cloud provider changes their privacy policy, their data processing agreement, or their logging practices, it doesn't affect us. Our data never touches their systems.
Full portability. Moving TraceNull to a different server, provider, or jurisdiction means copying the application files and the SQLite database. No database migration tools, no export/import procedures, no vendor lock-in.
When SQLite Is the Wrong Choice
We're advocates, not zealots. SQLite isn't right for every project:
- Multi-server write-heavy applications — if you need multiple application servers writing to the same database simultaneously, you need a client-server database (or something like LiteFS/Litestream for replication).
- Complex relational queries across massive datasets — if your analytics require joins across billions of rows, a columnar database will outperform SQLite significantly.
- Applications where the database must be shared across services — microservices architectures often assume a networked database. SQLite doesn't fit that pattern without additional tooling.
For a privacy-first URL shortener running on a single server? SQLite is close to ideal.
The Bigger Picture: Your Database Is a Privacy Decision
Most privacy discussions focus on what data you collect. That's important, but it's only half the story. Equally important is where that data lives and what systems can access it.
Every networked database is a potential data exposure point. Every managed service is a third-party processor under GDPR. Every cloud backup is a copy of user data in a location you may not fully control.
Choosing SQLite doesn't magically make your service private. You still have to make the right decisions about what to store (and what not to store). But it removes an entire layer of infrastructure that could undermine those decisions.
At TraceNull, our three-layer referrer stripping (Node.js headers, Caddy headers, and HTML meta tags) ensures no referrer data leaks. Our aggregate-only analytics ensure no individual tracking. And our SQLite database ensures that the data we do store never leaves the machine it was created on.
Privacy isn't just a policy. It's an architecture.
Try TraceNull — Privacy by Architecture
Shorten links, strip referrers, and keep your data where it belongs. Free tier available — no account required.
Create a Private Short Link