Documentation
¶
Overview ¶
Package sqliteconfig provides type-safe configuration for SQLite databases with proper enum validation and URL generation for modernc.org/sqlite driver.
Index ¶
Constants ¶
const (
// DefaultBusyTimeout is the default busy timeout in milliseconds.
DefaultBusyTimeout = 10000
)
Variables ¶
var ( ErrPathEmpty = errors.New("path cannot be empty") ErrBusyTimeoutNegative = errors.New("busy_timeout must be >= 0") ErrInvalidJournalMode = errors.New("invalid journal_mode") ErrInvalidAutoVacuum = errors.New("invalid auto_vacuum") ErrWALAutocheckpoint = errors.New("wal_autocheckpoint must be >= -1") ErrInvalidSynchronous = errors.New("invalid synchronous") ErrInvalidTxLock = errors.New("invalid txlock") )
Errors returned by config validation.
Functions ¶
This section is empty.
Types ¶
type AutoVacuum ¶
type AutoVacuum string
AutoVacuum represents SQLite auto_vacuum pragma values. Auto-vacuum controls how SQLite reclaims space from deleted data.
Performance vs Storage Tradeoffs:
INCREMENTAL - Recommended for production:
- Reclaims space gradually during normal operations
- Minimal performance impact on writes
- Database size shrinks automatically over time
- Can manually trigger with PRAGMA incremental_vacuum
- Good balance of space efficiency and performance
FULL - Automatic space reclamation:
- Immediately reclaims space on every DELETE/DROP
- Higher write overhead due to page reorganization
- Keeps database file size minimal
- Can cause significant slowdowns on large deletions
- Best for applications with frequent deletes and limited storage
NONE - No automatic space reclamation:
- Fastest write performance (no vacuum overhead)
- Database file only grows, never shrinks
- Deleted space is reused but file size remains large
- Requires manual VACUUM to reclaim space
- Best for write-heavy workloads where storage isn't constrained
const ( // AutoVacuumNone disables automatic space reclamation. // Fastest writes, file only grows. Requires manual VACUUM to reclaim space. AutoVacuumNone AutoVacuum = "NONE" // AutoVacuumFull immediately reclaims space on every DELETE/DROP. // Minimal file size but slower writes. Can impact performance on large deletions. AutoVacuumFull AutoVacuum = "FULL" // AutoVacuumIncremental reclaims space gradually (RECOMMENDED for production). // Good balance: minimal write impact, automatic space management over time. AutoVacuumIncremental AutoVacuum = "INCREMENTAL" )
func (AutoVacuum) IsValid ¶
func (a AutoVacuum) IsValid() bool
IsValid returns true if the AutoVacuum is valid.
func (AutoVacuum) String ¶
func (a AutoVacuum) String() string
String returns the string representation.
type Config ¶
type Config struct {
Path string // file path or ":memory:"
BusyTimeout int // milliseconds (0 = default/disabled)
JournalMode JournalMode // journal mode (affects concurrency and crash recovery)
AutoVacuum AutoVacuum // auto vacuum mode (affects storage efficiency)
WALAutocheckpoint int // pages (-1 = default/not set, 0 = disabled, >0 = enabled)
Synchronous Synchronous // synchronous mode (affects durability vs performance)
ForeignKeys bool // enable foreign key constraints (data integrity)
TxLock TxLock // transaction lock mode (affects write concurrency)
}
Config holds SQLite database configuration with type-safe enums. This configuration balances performance, durability, and operational requirements for Headscale's SQLite database usage patterns.
func Default ¶
Default returns the production configuration optimized for Headscale's usage patterns. This configuration prioritizes:
- Concurrent access (WAL mode for multiple readers/writers)
- Data durability with good performance (NORMAL synchronous)
- Automatic space management (INCREMENTAL auto-vacuum)
- Data integrity (foreign key constraints enabled)
- Safe concurrent writes (IMMEDIATE transaction lock)
- Reasonable timeout for busy database scenarios (10s)
type JournalMode ¶
type JournalMode string
JournalMode represents SQLite journal_mode pragma values. Journal modes control how SQLite handles write transactions and crash recovery.
Performance vs Durability Tradeoffs:
WAL (Write-Ahead Logging) - Recommended for production:
- Best performance for concurrent reads/writes
- Readers don't block writers, writers don't block readers
- Excellent crash recovery with minimal data loss risk
- Uses additional .wal and .shm files
- Default choice for Headscale production deployments
DELETE - Traditional rollback journal:
- Good performance for single-threaded access
- Readers block writers and vice versa
- Reliable crash recovery but with exclusive locking
- Creates temporary journal files during transactions
- Suitable for low-concurrency scenarios
TRUNCATE - Similar to DELETE but faster cleanup:
- Slightly better performance than DELETE
- Same concurrency limitations as DELETE
- Faster transaction commit by truncating instead of deleting journal
PERSIST - Journal file remains between transactions:
- Avoids file creation/deletion overhead
- Same concurrency limitations as DELETE
- Good for frequent small transactions
MEMORY - Journal kept in memory:
- Fastest performance but NO crash recovery
- Data loss risk on power failure or crash
- Only suitable for temporary or non-critical data
OFF - No journaling:
- Maximum performance but NO transaction safety
- High risk of database corruption on crash
- Should only be used for read-only or disposable databases
const ( // JournalModeWAL enables Write-Ahead Logging (RECOMMENDED for production). // Best concurrent performance + crash recovery. Uses additional .wal/.shm files. JournalModeWAL JournalMode = "WAL" // JournalModeDelete uses traditional rollback journaling. // Good single-threaded performance, readers block writers. Creates temp journal files. JournalModeDelete JournalMode = "DELETE" // JournalModeTruncate is like DELETE but with faster cleanup. // Slightly better performance than DELETE, same safety with exclusive locking. JournalModeTruncate JournalMode = "TRUNCATE" // JournalModePersist keeps journal file between transactions. // Good for frequent transactions, avoids file creation/deletion overhead. JournalModePersist JournalMode = "PERSIST" // JournalModeMemory keeps journal in memory (DANGEROUS). // Fastest performance but NO crash recovery - data loss on power failure. JournalModeMemory JournalMode = "MEMORY" // JournalModeOff disables journaling entirely (EXTREMELY DANGEROUS). // Maximum performance but high corruption risk. Only for disposable databases. JournalModeOff JournalMode = "OFF" )
func (JournalMode) IsValid ¶
func (j JournalMode) IsValid() bool
IsValid returns true if the JournalMode is valid.
func (JournalMode) String ¶
func (j JournalMode) String() string
String returns the string representation.
type Synchronous ¶
type Synchronous string
Synchronous represents SQLite synchronous pragma values. Synchronous mode controls how aggressively SQLite flushes data to disk.
Performance vs Durability Tradeoffs:
NORMAL - Recommended for production:
- Good balance of performance and safety
- Syncs at critical moments (transaction commits in WAL mode)
- Very low risk of corruption, minimal performance impact
- Safe with WAL mode even with power loss
- Default choice for most production applications
FULL - Maximum durability:
- Syncs to disk after every write operation
- Highest data safety, virtually no corruption risk
- Significant performance penalty (up to 50% slower)
- Recommended for critical data where corruption is unacceptable
EXTRA - Paranoid mode:
- Even more aggressive syncing than FULL
- Maximum possible data safety
- Severe performance impact
- Only for extremely critical scenarios
OFF - Maximum performance, minimum safety:
- No syncing, relies on OS to flush data
- Fastest possible performance
- High risk of corruption on power failure or crash
- Only suitable for non-critical or easily recreatable data
const ( // SynchronousOff disables syncing (DANGEROUS). // Fastest performance but high corruption risk on power failure. Avoid in production. SynchronousOff Synchronous = "OFF" // SynchronousNormal provides balanced performance and safety (RECOMMENDED). // Good performance with low corruption risk. Safe with WAL mode on power loss. SynchronousNormal Synchronous = "NORMAL" // SynchronousFull provides maximum durability with performance cost. // Syncs after every write. Up to 50% slower but virtually no corruption risk. SynchronousFull Synchronous = "FULL" // SynchronousExtra provides paranoid-level data safety (EXTREME). // Maximum safety with severe performance impact. Rarely needed in practice. SynchronousExtra Synchronous = "EXTRA" )
func (Synchronous) IsValid ¶
func (s Synchronous) IsValid() bool
IsValid returns true if the Synchronous is valid.
func (Synchronous) String ¶
func (s Synchronous) String() string
String returns the string representation.
type TxLock ¶ added in v0.28.0
type TxLock string
TxLock represents SQLite transaction lock mode. Transaction lock mode determines when write locks are acquired during transactions.
Lock Acquisition Behavior:
DEFERRED - SQLite default, acquire lock lazily:
- Transaction starts without any lock
- First read acquires SHARED lock
- First write attempts to upgrade to RESERVED lock
- If another transaction holds RESERVED: SQLITE_BUSY (potential deadlock)
- Can cause deadlocks when multiple connections attempt concurrent writes
IMMEDIATE - Recommended for write-heavy workloads:
- Transaction immediately acquires RESERVED lock at BEGIN
- If lock unavailable, waits up to busy_timeout before failing
- Other writers queue orderly instead of deadlocking
- Prevents the upgrade-lock deadlock scenario
- Slight overhead for read-only transactions that don't need locks
EXCLUSIVE - Maximum isolation:
- Transaction immediately acquires EXCLUSIVE lock at BEGIN
- No other connections can read or write
- Highest isolation but lowest concurrency
- Rarely needed in practice
const ( // TxLockDeferred acquires locks lazily (SQLite default). // Risk of SQLITE_BUSY deadlocks with concurrent writers. Use for read-heavy workloads. TxLockDeferred TxLock = "deferred" // TxLockImmediate acquires write lock immediately (RECOMMENDED for production). // Prevents deadlocks by acquiring RESERVED lock at transaction start. // Writers queue orderly, respecting busy_timeout. TxLockImmediate TxLock = "immediate" // TxLockExclusive acquires exclusive lock immediately. // Maximum isolation, no concurrent reads or writes. Rarely needed. TxLockExclusive TxLock = "exclusive" )