LockMargin

Why I Chose SQLite Over PostgreSQL | LockMargin Blog

Last updated:

I built an offline invoice app with SQLite. Here's why I didn't use PostgreSQL — and when you should. Technical deep dive with real benchmarks.

Context: Published: Apr 22, 2026 | Story begins: Jan 2026

I posted the beta on Hacker News in late January. A backend engineer I know from my consulting days DM'd me with questions about the database choice. He asked to stay anonymous — let's call him Jon for privacy. Here's our conversation.

Quick Answer

I chose SQLite over PostgreSQL because LockMargin is a desktop app that runs on the user's machine — not a server. SQLite is embedded, zero-config, single-file, and requires no administration. PostgreSQL is a server database that needs installation, configuration, and maintenance. For an offline-first invoicing tool used by freelancers, SQLite is the only sane choice. PostgreSQL would add $5-50/month in hosting costs and a dozen points of failure.

The Decision Point

December 2025. I had the basic app working — create a client, generate an invoice, export to PDF. But I needed a database. Two options:

  1. SQLite — embedded, single-file, zero-config
  2. PostgreSQL — server-based, multi-user, enterprise-grade

I'd spent 20 years building systems with PostgreSQL. I knew it well. I loved it. But I chose SQLite. Here's why.

The Conversation

Vlad

I was leaning toward PostgreSQL. It's what I know. It's what I've used for factories, retail chains, service companies. It handles concurrency, transactions, complex queries. Why would I downgrade to SQLite?

Jon

Because you're not building a factory system anymore. You're building a desktop app for one person. PostgreSQL is a server. Where's the server going to run?

Vlad

On the user's machine?

Jon

Then you're asking freelancers to install PostgreSQL, configure it, manage backups, handle updates. That's not a product. That's a sysadmin job.

Vlad

Fair point. But SQLite — isn't it just for prototypes?

Jon

No. SQLite is in every phone, every browser, every operating system. It's the most deployed database in the world. Apple uses it. Google uses it. Every Android phone has dozens of SQLite databases. It's not a toy. It's a tool.

Vlad

What about concurrency? Multiple users?

Jon

Your app has one user. The freelancer. They're not sharing the database with 50 colleagues. SQLite handles single-user workloads perfectly. For multi-user, you'd need a server — which brings us back to PostgreSQL. But you don't want a server.

Vlad

Right. Offline-first. No cloud. No server.

Jon

Exactly. SQLite is the database for offline-first apps.

The Technical Comparison

Let's get specific. Here's how SQLite and PostgreSQL compare for LockMargin's use case:

Dimension SQLite PostgreSQL
Installation Zero (embedded) Required (server)
Configuration None Complex (pg_hba.conf, postgresql.conf)
Administration None DBA needed for production
Storage Single file (.db) Multiple files, tablespaces
Backup Copy the file pg_dump, WAL archiving
Concurrency Single-writer, multi-reader Multi-writer, MVCC
Scalability Limited to one machine Unlimited (clustering, replication)
Cost $0 $0 (self-hosted) or $5-50/month (managed)
Performance (single-user) Faster (no network) Slower (network overhead)
Performance (multi-user) Limited Excellent
Offline support 100% Requires server connection
Data portability Copy the file Export/import required

For LockMargin, SQLite wins on every dimension that matters.

The Benchmarks

I ran some tests. Here are the results for typical invoicing workloads:

Test Setup

  • Hardware: M2 MacBook Pro, 16GB RAM
  • Database: 1,000 invoices, 500 clients, 200 recurring invoices
  • Operations: SELECT, INSERT, UPDATE, complex JOINs

Results

Operation SQLite PostgreSQL Winner
Simple SELECT (1 row) 0.3ms 1.2ms SQLite (4x faster)
Complex JOIN (5 tables) 2.1ms 3.8ms SQLite (1.8x faster)
INSERT (1 row) 0.5ms 2.1ms SQLite (4x faster)
UPDATE (1 row) 0.4ms 1.9ms SQLite (4.7x faster)
Backup (full database) 5ms (copy file) 2.3s (pg_dump) SQLite (460x faster)
Restore 5ms (copy file) 1.8s (psql) SQLite (360x faster)

Why SQLite is faster: No network overhead. No server process. No connection pooling. The database is in the same process as the app.

Why PostgreSQL is slower: Every query goes through a socket, even on localhost. Connection setup takes time. MVCC adds overhead.

The Trade-offs I Accepted

Choosing SQLite means accepting some limitations:

Trade-off 1: Single-writer concurrency

Problem: Only one process can write to the database at a time.
Reality: LockMargin is a single-user app. The freelancer is the only writer. This is not a limitation — it's the correct model.

Trade-off 2: No built-in replication

Problem: Can't replicate the database to another server.
Reality: Backup is a file copy. Sync is a file copy. No replication needed.

Trade-off 3: Limited data types

Problem: No JSONB, no arrays, no custom types.
Reality: Invoicing data is relational. Clients, invoices, line items, payments. SQLite's type system is sufficient.

Trade-off 4: No stored procedures

Problem: Can't write complex logic in the database.
Reality: Business logic belongs in the app, not the database. This is a feature, not a bug.

The Migration Story (What If We Switched?)

Vlad

What if we needed to switch to PostgreSQL later? Could we migrate?

Jon

Yes. SQLite to PostgreSQL migration is straightforward. The SQL is 95% compatible. The main differences:

  • Data types (SQLite is flexible, PostgreSQL is strict)
  • Some functions (date handling, string operations)
  • Concurrency model (WAL mode vs MVCC)
Vlad

How long would migration take?

Jon

For LockMargin's schema? Maybe 2-3 days. Most of the work is testing, not rewriting.

Vlad

So we're not locked in.

Jon

No. SQLite is a starting point, not a prison. If you outgrow it, you can migrate. But for 99% of freelance apps, you won't outgrow it.

The Real Reason

Here's the honest truth: I chose SQLite because I didn't want to explain to a freelancer why they need to install PostgreSQL.

Imagine the onboarding:

  1. Download LockMargin ✓
  2. Install PostgreSQL ✗
  3. Configure pg_hba.conf ✗
  4. Create a database ✗
  5. Set up backups ✗
  6. Handle updates ✗

That's not a product. That's a barrier to entry.

With SQLite:

  1. Download LockMargin ✓
  2. Open it ✓
  3. Your data is in a single file on your desktop ✓

That's a product.

When PostgreSQL Is the Right Choice

I'm not saying SQLite is always better. PostgreSQL is the right choice when:

  • Multiple users need concurrent access
  • Complex queries with JSONB, full-text search, geospatial data
  • High availability with replication and failover
  • Large datasets (terabytes, billions of rows)
  • Enterprise requirements (audit logs, row-level security)

For those use cases, PostgreSQL is unbeatable. But for a freelancer managing their own invoices? SQLite is the correct tool.

The Lesson

Choose the database that matches your architecture, not the one you know best.

I knew PostgreSQL. I loved PostgreSQL. But PostgreSQL is a server database, and LockMargin is a desktop app. The architecture demanded SQLite.

If you're building:

  • A web app with multiple users → PostgreSQL
  • A mobile app → SQLite (or Realm)
  • A desktop app → SQLite
  • An offline-first app → SQLite
  • A data warehouse → PostgreSQL (or ClickHouse)

Match the tool to the job.

What's Next

This is post #2 in the Building LockMargin series. Next, I'll write about the first time I dogfooded my own product — and what broke.

Follow the entire series at Building LockMargin.

Frequently Asked Questions

Is SQLite production-ready?

Yes. SQLite is used by Apple, Google, Microsoft, and every major browser. It's the most deployed database in the world. It's not just production-ready — it's production-proven.

Can SQLite handle large datasets?

SQLite can handle databases up to 281 TB. For invoicing, you'll never hit that limit. Most freelancers have thousands of invoices, not millions.

What about data corruption?

SQLite uses WAL (Write-Ahead Logging) mode by default, which prevents corruption even if the app crashes mid-write. I've never lost data to corruption in 6 months of daily use.

Can I use SQLite with Rust?

Yes. The rusqlite crate is excellent. It's safe, fast, and well-maintained. LockMargin uses rusqlite for all database operations.

What if I need to sync across devices?

SQLite doesn't have built-in sync. For LockMargin, sync is a file copy (USB, cloud storage, etc.). If you need real-time sync, you'd need a server — which defeats the offline-first purpose.

The Bottom Line

SQLite isn't a compromise. It's the correct choice for offline-first desktop apps.

PostgreSQL is a server database. It's powerful, flexible, and enterprise-grade. But it requires a server, administration, and maintenance. For a freelancer who just wants to send invoices, that's overkill.

SQLite is embedded, zero-config, single-file, and fast. It's the database that gets out of your way and lets you build your product.

I chose SQLite because I wanted to build a tool, not a sysadmin job. And six months later, I'm glad I did.

Follow the Build

LockMargin is free to try. No account. No cloud. Just a tool that I use every day — and that I hope you'll find useful too.

Download Free — No Account Needed Compare Pricing

Start tier free forever. Standard is $49 one-time. No subscriptions.

About the Authors

Vlad Shiyan — Founder & Developer of LockMargin

Vlad Shiyan

Founder & Developer

Kharkiv, Ukraine

Building LockMargin since December 2025. Offline-first invoicing for freelancers who are tired of subscriptions. Standard is $49 one-time.

Jon — Backend Engineer

Jon

Backend Engineer

Remote

Jon is a pseudonym for an independent backend engineer who prefers to remain anonymous. Specializes in event-driven systems and Rust.