Database Path
The database file location is controlled by theDUBLY_DB_PATH environment variable:
./dubly.db (current working directory)
The database file is created automatically on first startup if it doesn’t exist. Ensure the directory exists and Dubly has write permissions.
In production, use an absolute path on a persistent volume. Losing the database file means losing all links and analytics.
SQLite Pragmas
Dubly applies these pragmas on every database connection for optimal performance:WAL Mode
- Readers don’t block writers
- Writers don’t block readers
- Better performance under load
Busy Timeout
SQLITE_BUSY. This prevents immediate failures when the database is temporarily locked.
Synchronous Mode
NORMAL is safe and provides good performance. Data is synced at critical moments (checkpoints) rather than after every write.
Foreign Keys
Cache Size
Connection Pool
Dubly setsMaxOpenConns(1) to enforce single-writer access:
SQLITE_BUSY errors by serializing writes at the connection pool level rather than waiting for SQLite locks.
Implications:
- All writes are serialized through a single connection
- Reads use the same connection (safe with WAL mode)
- No risk of deadlocks or lock timeout errors
- Performance is excellent for Dubly’s read-heavy workload
Schema
The database schema is automatically created and migrated on startup.Links Table
Stores short link definitions:- Slug uniqueness is per-domain (composite unique constraint)
is_active=0implements soft deletes- Inactive links return
410 Goneon redirect
Clicks Table
Stores analytics events:Migrations
Dubly uses a simple migration strategy:CREATE TABLE IF NOT EXISTS and CREATE INDEX IF NOT EXISTS, making it idempotent. This approach works because:
- Dubly’s schema is stable
- There are no destructive changes needed
- Startup time impact is negligible
Soft Deletes
Dubly never hard-deletes links from the database. When you delete a link:is_activeis set to0- The row remains in the database
- Redirects for inactive links return
410 Gone - Slug uniqueness checks include inactive links
Backup Considerations
With WAL mode enabled, a complete backup requires three files:dubly.db- main database filedubly.db-wal- write-ahead logdubly.db-shm- shared memory file
- Use SQLite’s backup API (preferred)
- Stop Dubly before copying files
- Run
PRAGMA wal_checkpoint(TRUNCATE)before backup
Performance Characteristics
With the default configuration:- Redirects: < 1ms (with cache hit)
- Link creation: 1-5ms
- Analytics writes: Batched every 30s, non-blocking
- Database size: ~1 KB per link, ~200 bytes per click