Every application stores data somewhere, and for most web applications, that means a relational database. But which one? SQLite, PostgreSQL, and MySQL serve very different use cases despite sharing SQL as their query language.
This guide compares all three with honest benchmarks, real configuration differences, and practical advice for choosing the right database for your project and deployment workflow.
Quick Comparison
| Feature | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| Type | Embedded (serverless) | Client-server | Client-server |
| Storage | Single file | Server with data directory | Server with data directory |
| Setup | Zero configuration | Install + configure | Install + configure |
| Concurrent writes | Limited (file-level locking) | Excellent (MVCC) | Good (row-level locking with InnoDB) |
| Max database size | ~281 TB (theoretical) | Unlimited | Unlimited |
| JSON support | Basic (json functions) | Advanced (JSONB with indexing) | JSON type with functions |
| Full-text search | FTS5 extension | Built-in (ts_vector) | Built-in (InnoDB) |
| Replication | None | Streaming + logical | Primary-replica, Group Replication |
| Best for | Small apps, development, embedded | Complex apps, data integrity | Web apps, read-heavy workloads |
SQLite: The Embedded Database
SQLite isn't a server — it's a library that reads and writes directly to a single file on disk. There's no installation, no configuration, no separate process. Your application links against the SQLite library and talks directly to the database file.
Strengths
- Zero configuration: No server to install, configure, or maintain
- Single file: The entire database is one
.sqliteor.dbfile — easy to copy, backup, and move - Self-contained: No external dependencies
- Reliable: Used in every smartphone (iOS and Android), every web browser, and most operating systems
- Fast for reads: No network overhead since it's in-process
Limitations
- Concurrent writes: Only one writer at a time (readers can run concurrently). WAL mode improves this but doesn't match PostgreSQL
- No user management: No built-in authentication or access control
- Limited ALTER TABLE: Can't drop or rename columns in older versions (improved in 3.35.0+)
- No network access: The database file must be on the same machine as the application
When to Use SQLite
- Development and prototyping: Get started without setting up a database server
- Small-to-medium applications: Blogs, internal tools, single-server apps
- Mobile and desktop apps: The database ships with the application
- Embedded systems: IoT devices, configuration stores
- Testing: In-memory SQLite databases run tests fast with no cleanup
Configuration Example
import sqlite3
conn = sqlite3.connect('app.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
created_at TEXT DEFAULT CURRENT_TIMESTAMP
)
''')
PostgreSQL: The Enterprise Database
PostgreSQL is the most feature-rich open-source database. It emphasizes data integrity, SQL standards compliance, and extensibility. It handles complex queries, large datasets, and high-concurrency workloads.
Strengths
- Data integrity: Strict type checking, ACID compliance, foreign key enforcement
- Advanced features: JSONB, full-text search, window functions, CTEs, materialized views
- Extensibility: Custom types, functions, operators, and extensions (PostGIS, pgvector, TimescaleDB)
- Concurrency: MVCC (Multi-Version Concurrency Control) handles many concurrent writers efficiently
- SQL standards: Most standards-compliant open-source database
Limitations
- Setup complexity: Requires installation, configuration, and ongoing maintenance
- Resource usage: Higher memory and CPU usage than SQLite or MySQL for simple workloads
- Shared hosting: Less commonly available on basic hosting plans
- Learning curve: Advanced features require deeper PostgreSQL knowledge
When to Use PostgreSQL
- Complex applications: Apps with complex queries, relationships, and data integrity requirements
- Analytics and reporting: Window functions, CTEs, and materialized views
- Geospatial data: PostGIS extension is the gold standard
- JSON-heavy workloads: JSONB with GIN indexes is powerful
- High-concurrency writes: MVCC handles many concurrent writers well
Configuration Example
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email TEXT UNIQUE NOT NULL,
name TEXT NOT NULL,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- GIN index on JSONB for fast queries
CREATE INDEX idx_users_metadata ON users USING GIN (metadata);
-- Full-text search
ALTER TABLE users ADD COLUMN search_vector tsvector;
CREATE INDEX idx_users_search ON users USING GIN (search_vector);
MySQL: The Web Database
MySQL (and its fork MariaDB) has been the default database for web applications since the early 2000s. It's the M
in LAMP (Linux, Apache, MySQL, PHP) and remains the most widely deployed database in web hosting.
Strengths
- Ubiquity: Available on virtually every hosting platform, including shared hosting
- Read performance: Optimized for read-heavy web workloads
- Replication: Mature primary-replica replication for scaling reads
- Ecosystem: Massive community, extensive tooling, widespread ORM support
- WordPress: Powers 40%+ of the web through WordPress
Limitations
- Less strict by default: Older versions silently truncate data or accept invalid dates — modern versions (8.0+) improved this significantly
- Fewer advanced features: No native JSONB indexing (until recently), limited window function support in older versions
- Storage engine complexity: InnoDB vs MyISAM distinction can confuse beginners
When to Use MySQL
- Web applications: Traditional LAMP/LEMP stack applications
- WordPress sites: WordPress requires MySQL (or MariaDB)
- Read-heavy workloads: MySQL excels at simple SELECT queries at scale
- Shared hosting: When it's the only database available
- Legacy systems: Migrating away from MySQL is often more work than staying
Configuration Example
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
metadata JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SQL Syntax Differences
Despite all three using SQL, there are syntax differences that matter when writing queries or switching databases:
| Feature | SQLite | PostgreSQL | MySQL |
|---|---|---|---|
| Auto-increment | AUTOINCREMENT |
SERIAL or GENERATED ALWAYS |
AUTO_INCREMENT |
| Boolean type | Integer (0/1) | Native BOOLEAN |
TINYINT(1) |
| String concat | `\ | \ | ` |
| Current time | CURRENT_TIMESTAMP |
NOW() |
NOW() |
| UPSERT | INSERT OR REPLACE |
ON CONFLICT DO UPDATE |
ON DUPLICATE KEY UPDATE |
| LIMIT with offset | LIMIT n OFFSET m |
LIMIT n OFFSET m |
LIMIT m, n or LIMIT n OFFSET m |
ORMs like Prisma, SQLAlchemy, Django ORM, and ActiveRecord abstract these differences, letting you switch databases without rewriting queries (in theory — in practice, database-specific features often creep in).
How Database Choice Affects Deployment
Your database choice has direct implications for how you deploy and manage your application:
SQLite Deployments
SQLite's database file lives alongside your application code. This creates a unique deployment challenge:
your-app/
├── app.js
├── database.sqlite ← This is your database
├── package.json
└── ...
When deploying with DeployHQ, you need to be careful:
- Don't overwrite the database on every deploy. Exclude
*.sqliteand*.dbfrom your deployment or use DeployHQ's excluded files feature - Backups are simple: Just copy the file
- No connection string needed: The file path is the connection
PostgreSQL and MySQL Deployments
These databases run as separate servers. Your application connects via a connection string:
# PostgreSQL
DATABASE_URL=postgres://user:password@db-server:5432/myapp
# MySQL
DATABASE_URL=mysql://user:password@db-server:3306/myapp
Store these connection strings as environment variables — never hardcode them. DeployHQ's build pipelines can inject these securely during deployment.
Migrations
All three databases need schema migrations as your application evolves. Run migrations as part of your deployment:
# In your DeployHQ build command
npm ci
npm run build
npm run db:migrate
Whether you push from GitHub or GitLab, DeployHQ runs your build commands (including migrations) before transferring files to the server.
For agencies managing client databases, PostgreSQL and MySQL offer user-level access control — you can give each client's app its own database user with restricted permissions.
FAQ
Can I start with SQLite and migrate to PostgreSQL later? Yes, if you use an ORM. The ORM abstracts SQL differences, making the switch mostly painless. Test thoroughly — there are always edge cases with date handling, string comparison, and JSON support.
Which database is fastest? It depends on the workload. SQLite is fastest for single-user read-heavy applications (no network overhead). PostgreSQL handles concurrent writes best. MySQL is optimized for simple read queries at scale. Benchmark your actual workload rather than relying on generic benchmarks.
Do I need PostgreSQL for a simple blog? No. SQLite or MySQL are fine for simple applications. Choose PostgreSQL when you need advanced features like JSONB, full-text search, or complex analytical queries.
Is MariaDB the same as MySQL? MariaDB forked from MySQL in 2009 and is largely compatible. Most MySQL applications work with MariaDB without changes. MariaDB has diverged more in recent versions, adding unique features, but the core SQL and wire protocol remain compatible.
Which database does DeployHQ recommend? DeployHQ works with any database — it deploys your application code, and your application connects to whatever database you've set up. For new projects, PostgreSQL is the most versatile choice.
There's no universally best
database — only the right one for your project. SQLite for simplicity, PostgreSQL for power, MySQL for ubiquity. Pick the one that matches your needs and deploy it confidently.
Try DeployHQ free — deploy your application with any database and manage connection strings securely. See pricing for team plans.
Questions? Reach out at support@deployhq.com or @deployhq.