SQLite Database¶
BorgBoi uses SQLite for local metadata and cache storage. The database file is:
~/.borgboi/.database/borgboi.db
If BORGBOI_HOME is set, the path becomes:
$BORGBOI_HOME/.borgboi/.database/borgboi.db
What SQLite Stores¶
SQLite stores:
- Repository metadata (
repositories) - Cached S3 statistics (
s3_stats_cache) - Storage schema version (
schema_version)
It does not store the Borg repository contents themselves. Actual backup archives remain in Borg repositories on disk (and optionally S3).
Database Lifecycle¶
flowchart TD
A[Start SQLiteStorage] --> B{DB file exists?}
B -- Yes --> C[Open DB engine]
B -- No --> D[Check legacy JSON data dirs]
D --> E{Legacy data found?}
E -- No --> F[Create empty SQLite DB]
E -- Yes --> G[Create SQLite DB]
G --> H[Migrate legacy repository JSON]
G --> I[Migrate legacy S3 stats cache JSON]
H --> C
I --> C
F --> C
C --> J[Ensure tables exist]
J --> K[Ensure schema_version row exists]
K --> L[Use DB for reads and writes]
Schema Overview¶
erDiagram
REPOSITORIES {
INTEGER id PK
STRING name UK
STRING path
STRING backup_target
STRING hostname
STRING os_platform
DATETIME last_backup
TEXT metadata_json
INTEGER retention_keep_daily
INTEGER retention_keep_weekly
INTEGER retention_keep_monthly
INTEGER retention_keep_yearly
DATETIME last_s3_sync
DATETIME created_at
STRING passphrase
STRING passphrase_file_path
BOOLEAN passphrase_migrated
DATETIME updated_at
}
S3_STATS_CACHE {
INTEGER id PK
STRING repo_name UK
BIGINT total_size_bytes
INTEGER object_count
DATETIME last_modified
DATETIME cached_at
}
SCHEMA_VERSION {
INTEGER id PK
INTEGER version
DATETIME applied_at
}
REPOSITORIES ||--o| S3_STATS_CACHE : "repo name (app-level)"
Relationship model
repositories and s3_stats_cache are related by repository name at the application layer (repositories.name <-> s3_stats_cache.repo_name).
The current schema does not define a SQL foreign key constraint for this link.
Table Details¶
repositories¶
Primary table for BorgBoi repository metadata.
| Column | Type | Nullable | Constraints / Behavior |
|---|---|---|---|
id |
INTEGER |
No | Primary key, auto-increment |
name |
VARCHAR(255) |
No | Unique, indexed |
path |
VARCHAR(1024) |
No | Used with hostname for uniqueness |
backup_target |
VARCHAR(1024) |
No | Filesystem path being backed up |
hostname |
VARCHAR(255) |
No | Indexed |
os_platform |
VARCHAR(10) |
No | Host OS identifier |
last_backup |
DATETIME |
Yes | Last successful backup timestamp |
metadata_json |
TEXT |
Yes | Serialized repository info payload |
retention_keep_daily |
INTEGER |
Yes | Optional per-repo retention override |
retention_keep_weekly |
INTEGER |
Yes | Optional per-repo retention override |
retention_keep_monthly |
INTEGER |
Yes | Optional per-repo retention override |
retention_keep_yearly |
INTEGER |
Yes | Optional per-repo retention override |
last_s3_sync |
DATETIME |
Yes | Last S3 synchronization time |
created_at |
DATETIME |
Yes | Creation timestamp when set |
passphrase |
VARCHAR(512) |
Yes | Legacy/inline passphrase storage |
passphrase_file_path |
VARCHAR(1024) |
Yes | File path to passphrase material |
passphrase_migrated |
BOOLEAN |
No | Defaults to false |
updated_at |
DATETIME |
No | Auto-set on write and update |
Additional unique constraint:
UNIQUE(path, hostname)viauq_repo_path_hostname
This allows the same path string to exist on different hosts while preventing duplicates on the same host.
s3_stats_cache¶
Caches S3 statistics for each repository to reduce repeated API calls.
| Column | Type | Nullable | Constraints / Behavior |
|---|---|---|---|
id |
INTEGER |
No | Primary key, auto-increment |
repo_name |
VARCHAR(255) |
No | Unique (one cache row per repository name) |
total_size_bytes |
BIGINT |
No | Defaults to 0 |
object_count |
INTEGER |
No | Defaults to 0 |
last_modified |
DATETIME |
Yes | Last modified timestamp observed in S3 |
cached_at |
DATETIME |
No | Timestamp when cache row was written |
schema_version¶
Tracks storage schema version.
| Column | Type | Nullable | Constraints / Behavior |
|---|---|---|---|
id |
INTEGER |
No | Primary key, auto-increment |
version |
INTEGER |
No | Current schema version |
applied_at |
DATETIME |
No | Timestamp when this version row was inserted |
Current initialization behavior inserts version 1 if no row exists.
Operational Notes¶
- SQLite is opened with
PRAGMA journal_mode=WALto improve concurrent read behavior. - Tables are created through SQLAlchemy metadata (
create_all) during initialization. - Deleting a repository also deletes its
s3_stats_cacherow in application logic. - Exclusions are not stored in SQLite; they are written to text files under
~/.borgboi/data/exclusions/.
Common Introspection Queries¶
-- Show repository rows
SELECT id, name, path, hostname, last_backup, updated_at
FROM repositories
ORDER BY name;