litestream-coder
This skill guides configuring Litestream for continuous SQLite backup in Rails 8+ apps. Use when setting up production backups for SQLite databases (Solid Queue, Solid Cache, Solid Cable).
What this skill does
# Litestream Coder
## Overview
Litestream provides continuous streaming backup for SQLite databases to S3-compatible storage. Essential for Rails 8+ apps using SQLite in production with Solid Queue, Solid Cache, and Solid Cable.
## Configuration File
Create `config/litestream.yml`:
```yaml
dbs:
- path: /rails/storage/production.sqlite3
replicas:
- type: s3
bucket: ${BUCKET_NAME}
path: sqlite/production
endpoint: ${S3_ENDPOINT}
region: ${S3_REGION}
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
force-path-style: true # Required for S3-compatible storage
sync-interval: 5s # How often to sync WAL
snapshot-interval: 1h # Full snapshot frequency
retention: 168h # 7 days
retention-check-interval: 1h
validation-interval: 12h
```
## Retention Strategies by Database Type
**Primary database (production.sqlite3):**
- `sync-interval: 5s` - Frequent syncing for data durability
- `snapshot-interval: 1h` - Hourly snapshots
- `retention: 720h` - 30 days for recovery
**Cache database (production_cache.sqlite3):**
- `sync-interval: 10s` - Less critical, reduce load
- `snapshot-interval: 6h` - Less frequent
- `retention: 24h` - 1 day sufficient
**Queue database (production_queue.sqlite3):**
- `sync-interval: 5s` - Important for job durability
- `snapshot-interval: 1h` - Hourly
- `retention: 72h` - 3 days for debugging
**Cable database (production_cable.sqlite3):**
- `sync-interval: 10s` - Ephemeral data
- `snapshot-interval: 6h` - Infrequent
- `retention: 24h` - 1 day
## Complete Configuration Example
```yaml
dbs:
- path: /rails/storage/production.sqlite3
replicas:
- type: s3
bucket: myapp-backups
path: sqlite/production
endpoint: https://fsn1.your-objectstorage.com
region: fsn1
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
force-path-style: true
sync-interval: 5s
snapshot-interval: 1h
retention: 720h
retention-check-interval: 1h
validation-interval: 12h
- path: /rails/storage/production_cache.sqlite3
replicas:
- type: s3
bucket: myapp-backups
path: sqlite/cache
endpoint: https://fsn1.your-objectstorage.com
region: fsn1
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
force-path-style: true
sync-interval: 10s
snapshot-interval: 6h
retention: 24h
- path: /rails/storage/production_queue.sqlite3
replicas:
- type: s3
bucket: myapp-backups
path: sqlite/queue
endpoint: https://fsn1.your-objectstorage.com
region: fsn1
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
force-path-style: true
sync-interval: 5s
snapshot-interval: 1h
retention: 72h
- path: /rails/storage/production_cable.sqlite3
replicas:
- type: s3
bucket: myapp-backups
path: sqlite/cable
endpoint: https://fsn1.your-objectstorage.com
region: fsn1
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
force-path-style: true
sync-interval: 10s
snapshot-interval: 6h
retention: 24h
```
## Kamal 2 Deployment
Add Litestream as an accessory in `config/deploy.yml`:
```yaml
accessories:
litestream:
image: litestream/litestream:0.3
host: <SERVER_IP>
cmd: replicate
volumes:
- "myapp_storage:/rails/storage:ro" # Read-only access
files:
- config/litestream.yml:/etc/litestream.yml
env:
secret:
- LITESTREAM_ACCESS_KEY_ID
- LITESTREAM_SECRET_ACCESS_KEY
options:
health-cmd: "litestream databases || exit 1"
health-interval: 30s
health-timeout: 5s
health-retries: 3
```
**Key points:**
- Mount storage as read-only (`:ro`) - Litestream only reads WAL files
- Use same volume name as main app
- Health check verifies Litestream can see databases
## Secrets Configuration
In `.kamal/secrets`:
```bash
LITESTREAM_ACCESS_KEY_ID=$(op read "op://myproject/production-s3/access_key_id")
LITESTREAM_SECRET_ACCESS_KEY=$(op read "op://myproject/production-s3/secret_access_key")
```
## Disaster Recovery
### Restore Database
```bash
# Stop application first
kamal app stop
# Restore from latest backup
docker run --rm \
-v myapp_storage:/rails/storage \
-e LITESTREAM_ACCESS_KEY_ID="$(op read 'op://myproject/production-s3/access_key_id')" \
-e LITESTREAM_SECRET_ACCESS_KEY="$(op read 'op://myproject/production-s3/secret_access_key')" \
litestream/litestream:0.3 restore \
-config /etc/litestream.yml \
/rails/storage/production.sqlite3
# Restart application
kamal app start
```
### Point-in-Time Recovery
```bash
docker run --rm \
-v myapp_storage:/rails/storage \
-e LITESTREAM_ACCESS_KEY_ID="..." \
-e LITESTREAM_SECRET_ACCESS_KEY="..." \
litestream/litestream:0.3 restore \
-config /etc/litestream.yml \
-timestamp "2025-01-15T10:30:00Z" \
/rails/storage/production.sqlite3
```
## Monitoring
Check backup status:
```bash
# Via Kamal
kamal accessory exec litestream -- litestream databases
# Direct on server
docker exec myapp-litestream litestream databases
```
## S3-Compatible Storage
Litestream works with any S3-compatible storage:
| Provider | Endpoint Example |
|----------|------------------|
| Hetzner Object Storage | `https://fsn1.your-objectstorage.com` |
| Backblaze B2 | `https://s3.us-west-002.backblazeb2.com` |
| DigitalOcean Spaces | `https://nyc3.digitaloceanspaces.com` |
| AWS S3 | (omit endpoint, use region) |
**Critical:** Always set `force-path-style: true` for non-AWS S3-compatible storage.
## VACUUM Impact on Litestream
Full `VACUUM` rewrites the entire database file. Litestream detects this as a complete change and triggers a **full snapshot** upload (not incremental WAL sync).
**Operational considerations:**
- VACUUM increases backup storage temporarily (old snapshot + new snapshot retained during retention window)
- Stagger VACUUM across databases to avoid bandwidth spikes: primary at 3:00, cache at 3:15, queue at 3:30
- This is expected and safe — don't disable VACUUM to avoid snapshots
- Monitor with `litestream databases` after VACUUM to confirm snapshot completed
See `resources/database-admin/sqlite.md` for VACUUM scheduling strategies.
## Best Practices
- **Separate databases by retention needs** - Main DB needs longer retention than cache
- **Monitor backup lag** - `litestream databases` shows replication status
- **Test restores regularly** - Don't wait for a disaster to verify backups work
- **Use read-only mount** - Litestream only reads WAL files, `:ro` prevents accidents
- **Stagger VACUUM operations** - Avoid simultaneous full snapshots across databases
Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.