diff --git a/.cursor-plugin/plugin.json b/.cursor-plugin/plugin.json index 6ac7d69..6ac1cee 100644 --- a/.cursor-plugin/plugin.json +++ b/.cursor-plugin/plugin.json @@ -2,7 +2,7 @@ "name": "database-skills", "displayName": "PlanetScale Database Skills", "version": "1.0.0", - "description": "Database-focused skills for MySQL, Postgres, Vitess, and Neki workflows.", + "description": "Database-focused skills for MySQL, Postgres, SQLite, Vitess, and Neki workflows.", "author": { "name": "PlanetScale" }, @@ -14,6 +14,7 @@ "database", "mysql", "postgres", + "sqlite", "vitess", "neki", "planetscale" diff --git a/README.md b/README.md index d90567a..eb466af 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,10 @@ Overview and guidance for Neki, PlanetScale's sharded Postgres product. Use when PostgreSQL best practices, query optimization, connection troubleshooting, and performance insights for PlanetScale Postgres. Use when working with PlanetScale PostgreSQL databases — schema design, indexing, MVCC/VACUUM, WAL tuning, replication, monitoring, or PlanetScale-specific features like connection pooling and CLI insights. +### sqlite + +SQLite best practices for schema design, indexing, query planning, WAL/checkpoint tuning, transactions, and safe migrations. Use when building or debugging embedded/mobile/edge SQLite workloads and local application databases. + ### vitess Vitess best practices, query optimization, and connection troubleshooting for PlanetScale Vitess databases. Use when working with sharding, VSchema configuration, keyspace management, online DDL, VReplication, or MySQL-compatible scaling issues. @@ -57,6 +61,9 @@ database-skills/ ├── postgres/ │ ├── SKILL.md │ └── references/ + ├── sqlite/ + │ ├── SKILL.md + │ └── references/ └── vitess/ ├── SKILL.md └── references/ diff --git a/skills/sqlite/SKILL.md b/skills/sqlite/SKILL.md new file mode 100644 index 0000000..7e8b0ba --- /dev/null +++ b/skills/sqlite/SKILL.md @@ -0,0 +1,67 @@ +--- +name: sqlite +description: Plan and review SQLite schema, indexing, query plans, transactions, and operational settings. Use when building embedded/local databases, tuning mobile or edge workloads, planning migrations, or debugging lock/contention behavior. +--- + +# SQLite + +Use this skill to make safe, measurable SQLite changes for production apps and local tooling. + +## Workflow +1. Define environment and workload (SQLite version, app runtime, storage medium, read/write pattern, concurrency model). +2. Read only the relevant reference files linked in each section below. +3. Propose the smallest change that solves the issue, including trade-offs. +4. Validate with evidence (`EXPLAIN QUERY PLAN`, `ANALYZE`, timing, lock behavior, and rollback steps). +5. For production changes, include migration safety, checkpoint strategy, and post-deploy verification. + +## Data Modeling +- Keep hot tables narrow; use `INTEGER PRIMARY KEY` when possible for rowid-backed lookups. +- Use `STRICT` tables (3.37+) for type safety in app-facing schemas. +- Enable and enforce foreign keys (`PRAGMA foreign_keys = ON`) on every connection. +- Store timestamps in one consistent format (usually UTC ISO-8601 text) and document it. + +References: +- [data-modeling](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/data-modeling.md) + +## Indexing and Query Planning +- Build composite indexes in predicate order (equality columns before range/sort columns). +- Prefer covering indexes for high-frequency reads. +- Avoid functions on indexed columns in `WHERE` unless expression indexes are used. +- Re-run `ANALYZE` after major data distribution changes; use `PRAGMA optimize` periodically for low-touch maintenance. + +References: +- [indexing-query-planner](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/indexing-query-planner.md) +- [diagnostics](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/diagnostics.md) + +## Transactions and Concurrency +- Use explicit transactions for write batches; keep them short. +- Prefer `BEGIN IMMEDIATE` for write-heavy code paths to fail fast on lock contention. +- Configure a `busy_timeout` and implement bounded retries with jitter. +- Keep long-running reads from blocking checkpoints and writers. + +References: +- [transactions-locking](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/transactions-locking.md) +- [wal-checkpointing](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/wal-checkpointing.md) + +## Pragmas and Performance Tuning +- Prefer `journal_mode=WAL` for mixed read/write workloads. +- Tune `synchronous` to durability needs (`FULL` for max safety, `NORMAL` for many app workloads). +- Size cache and temp storage intentionally (`cache_size`, `temp_store`, `mmap_size`). +- Avoid blanket PRAGMA changes without benchmarking representative traffic. + +References: +- [pragmas-tuning](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/pragmas-tuning.md) + +## Migrations and Operations +- Use additive migrations first; backfill before enforcing new constraints. +- For table rewrites, use create-copy-swap patterns with integrity checks. +- Always run `PRAGMA foreign_key_check` and `PRAGMA integrity_check` after risky schema changes. +- Add backup and restore steps before destructive migrations. + +References: +- [migrations-operations](https://raw.githubusercontent.com/planetscale/database-skills/main/skills/sqlite/references/migrations-operations.md) + +## Guardrails +- Prefer evidence over assumptions; include measured before/after results. +- Call out version-specific behavior (for example, `STRICT` tables, `RETURNING`, `ALTER TABLE` support). +- Ask for explicit human approval before destructive data operations (drops/deletes/truncates). diff --git a/skills/sqlite/references/data-modeling.md b/skills/sqlite/references/data-modeling.md new file mode 100644 index 0000000..bdadb88 --- /dev/null +++ b/skills/sqlite/references/data-modeling.md @@ -0,0 +1,57 @@ +--- +title: SQLite Data Modeling +description: Practical schema design patterns for maintainable SQLite databases +tags: sqlite, schema, data-types, foreign-keys, strict-tables +--- + +# SQLite Data Modeling + +## Prefer predictable primary keys + +```sql +CREATE TABLE account ( + id INTEGER PRIMARY KEY, + email TEXT NOT NULL UNIQUE, + created_at TEXT NOT NULL +) STRICT; +``` + +- `INTEGER PRIMARY KEY` aliases the rowid and is the most efficient lookup path. +- Avoid random-text primary keys for hot write paths; keep external IDs in a separate indexed column. + +## Use STRICT tables when available + +`STRICT` (SQLite 3.37+) enforces type constraints more like server databases. + +```sql +CREATE TABLE event ( + id INTEGER PRIMARY KEY, + kind TEXT NOT NULL, + payload TEXT NOT NULL, + happened_at TEXT NOT NULL +) STRICT; +``` + +## Foreign keys are disabled by default + +Enable on every connection before statements that rely on referential integrity: + +```sql +PRAGMA foreign_keys = ON; +``` + +Validate after migrations: + +```sql +PRAGMA foreign_key_check; +``` + +## Represent booleans and timestamps intentionally + +- Booleans: store as `INTEGER` (`0`/`1`) with `CHECK (flag IN (0,1))` when needed. +- Timestamps: store as UTC ISO-8601 `TEXT` consistently, or Unix epoch `INTEGER` consistently. + +## Add constraints early + +- Use `NOT NULL`, `CHECK`, and `UNIQUE` constraints to prevent bad data entering the file. +- Add app-level validation too; SQLite constraints are the final safety net, not the first. diff --git a/skills/sqlite/references/diagnostics.md b/skills/sqlite/references/diagnostics.md new file mode 100644 index 0000000..f45376e --- /dev/null +++ b/skills/sqlite/references/diagnostics.md @@ -0,0 +1,43 @@ +--- +title: SQLite Diagnostics +description: Query plan inspection and troubleshooting workflow +tags: sqlite, explain, diagnostics, analyze, performance +--- + +# SQLite Diagnostics + +## Plan inspection + +```sql +EXPLAIN QUERY PLAN +SELECT id, status FROM orders +WHERE tenant_id = 42 +ORDER BY created_at DESC +LIMIT 20; +``` + +Look for: + +- `SCAN table` -> full scan (often a missing/unused index) +- `SEARCH table USING INDEX ...` -> index usage +- `USING COVERING INDEX ...` -> no table lookup needed +- `USE TEMP B-TREE` -> sort/group spill; check index support + +## Repeatable tuning loop + +1. Capture baseline latency and row counts. +2. Inspect `EXPLAIN QUERY PLAN` output. +3. Add or adjust indexes/query shape. +4. Run `ANALYZE` and compare metrics again. +5. Keep only changes with measurable gains. + +## Helpful commands + +```sql +SELECT sqlite_version(); +ANALYZE; +PRAGMA optimize; +PRAGMA compile_options; +``` + +Version and compile options explain feature availability and behavior differences across environments. diff --git a/skills/sqlite/references/indexing-query-planner.md b/skills/sqlite/references/indexing-query-planner.md new file mode 100644 index 0000000..537f20d --- /dev/null +++ b/skills/sqlite/references/indexing-query-planner.md @@ -0,0 +1,52 @@ +--- +title: SQLite Indexing and Query Planner +description: Index design and planner behavior for fast SQLite queries +tags: sqlite, indexes, query-planner, explain, performance +--- + +# SQLite Indexing and Query Planner + +## Composite index ordering + +Put equality predicates first, then range/sort predicates. + +```sql +-- Query pattern: +-- WHERE tenant_id = ? AND status = ? AND created_at >= ? ORDER BY created_at DESC +CREATE INDEX idx_orders_tenant_status_created + ON orders(tenant_id, status, created_at DESC); +``` + +## Covering indexes + +If a query only needs indexed columns, SQLite can avoid table lookups. + +```sql +-- SELECT id, created_at FROM orders WHERE tenant_id=? ORDER BY created_at DESC LIMIT 50 +CREATE INDEX idx_orders_tenant_created_id + ON orders(tenant_id, created_at DESC, id); +``` + +## Expression and partial indexes + +Use them only when the predicate is stable and common. + +```sql +CREATE INDEX idx_user_lower_email ON user(lower(email)); +CREATE INDEX idx_task_open ON task(updated_at) WHERE status = 'open'; +``` + +## Common planner pitfalls + +- Functions on indexed columns usually prevent normal index use unless expression index matches exactly. +- `OR` conditions can split plans; rewrite to `UNION ALL` when selective branches exist. +- Deep `OFFSET` pagination gets slower; prefer keyset pagination. + +## Keep stats fresh + +Run after major data changes so the planner chooses better paths: + +```sql +ANALYZE; +PRAGMA optimize; +``` diff --git a/skills/sqlite/references/migrations-operations.md b/skills/sqlite/references/migrations-operations.md new file mode 100644 index 0000000..c257a2b --- /dev/null +++ b/skills/sqlite/references/migrations-operations.md @@ -0,0 +1,44 @@ +--- +title: SQLite Migrations and Operations +description: Safe migration patterns, backups, and integrity verification +tags: sqlite, migrations, ddl, backup, integrity-check +--- + +# SQLite Migrations and Operations + +## Pre-migration checklist + +- Capture a backup (`.backup` in sqlite3 CLI or file-level snapshot when safe). +- Record SQLite version (`SELECT sqlite_version();`) to validate feature support. +- Confirm foreign keys are enabled during migration sessions. + +## Additive-first migration pattern + +1. Add new nullable columns/tables/indexes. +2. Backfill in chunks. +3. Switch application reads/writes. +4. Enforce stricter constraints after backfill validation. + +## Table rewrite pattern (create-copy-swap) + +When direct `ALTER TABLE` support is limited: + +```sql +BEGIN IMMEDIATE; +CREATE TABLE new_table (...); +INSERT INTO new_table (...) SELECT ... FROM old_table; +DROP TABLE old_table; +ALTER TABLE new_table RENAME TO old_table; +COMMIT; +``` + +Recreate indexes, triggers, and foreign keys explicitly as part of the migration. + +## Post-migration validation + +```sql +PRAGMA foreign_key_check; +PRAGMA integrity_check; +``` + +Also validate row counts and key business invariants before marking migration complete. diff --git a/skills/sqlite/references/pragmas-tuning.md b/skills/sqlite/references/pragmas-tuning.md new file mode 100644 index 0000000..631b74f --- /dev/null +++ b/skills/sqlite/references/pragmas-tuning.md @@ -0,0 +1,48 @@ +--- +title: SQLite PRAGMAs and Tuning +description: Safe performance tuning using SQLite runtime settings +tags: sqlite, pragma, tuning, cache, memory +--- + +# SQLite PRAGMAs and Tuning + +## Measure first + +PRAGMAs change behavior globally for a connection or database file. Benchmark before and after under representative load. + +## High-impact settings + +```sql +PRAGMA cache_size = -32768; -- about 32 MB cache (negative = KB) +PRAGMA temp_store = MEMORY; -- keep temp objects in memory when feasible +PRAGMA mmap_size = 268435456; -- 256 MB mapped I/O if platform supports it +``` + +- Larger cache helps read-heavy workloads, but increases memory use. +- `temp_store=MEMORY` can improve sorts/joins but may increase RSS. +- `mmap_size` can reduce syscall overhead on capable filesystems. + +## Safety settings + +```sql +PRAGMA foreign_keys = ON; +PRAGMA trusted_schema = OFF; +``` + +- Always enable foreign keys unless there is a specific documented reason not to. +- `trusted_schema=OFF` reduces risk from malicious schema-level SQL in untrusted files. + +## Planner maintenance settings + +```sql +PRAGMA analysis_limit = 2000; +PRAGMA optimize; +``` + +- `PRAGMA optimize` may run targeted `ANALYZE` work when statistics are stale or missing. +- Use explicit `ANALYZE` after large data shifts; use `PRAGMA optimize` as periodic maintenance. + +## Avoid blanket advice + +- `synchronous=OFF` is risky for most production apps. +- Revisit tuning after schema/index changes; bottlenecks move. diff --git a/skills/sqlite/references/transactions-locking.md b/skills/sqlite/references/transactions-locking.md new file mode 100644 index 0000000..3411a02 --- /dev/null +++ b/skills/sqlite/references/transactions-locking.md @@ -0,0 +1,49 @@ +--- +title: SQLite Transactions and Locking +description: Contention patterns and reliable transaction usage in SQLite +tags: sqlite, transactions, locking, concurrency, busy-timeout +--- + +# SQLite Transactions and Locking + +## Transaction modes + +```sql +BEGIN; -- deferred (default) +BEGIN IMMEDIATE; -- reserve write lock up front +BEGIN EXCLUSIVE; -- strongest lock mode +``` + +- `BEGIN` (deferred) delays locking until first write. +- `BEGIN IMMEDIATE` is usually best for write paths; it surfaces contention early. +- Keep write transactions short to reduce `database is locked` errors. + +## Busy handling + +Set timeout per connection and add bounded app retries. + +```sql +PRAGMA busy_timeout = 5000; +``` + +- Do not retry forever; use jitter and a max attempt count. +- Log lock wait time to identify saturation. +- Some lock-upgrade conflicts fail fast with `SQLITE_BUSY` to avoid deadlock; design retry logic accordingly. + +## WAL-aware behavior + +- In WAL mode, readers do not block writers, but one writer still serializes writes. +- Long-lived readers can delay checkpoints and grow WAL files. + +## Savepoints for partial rollback + +```sql +BEGIN IMMEDIATE; +SAVEPOINT step1; +-- changes +ROLLBACK TO step1; -- optional partial rollback +RELEASE step1; +COMMIT; +``` + +Use savepoints to isolate chunks inside larger business transactions. diff --git a/skills/sqlite/references/wal-checkpointing.md b/skills/sqlite/references/wal-checkpointing.md new file mode 100644 index 0000000..a0237ba --- /dev/null +++ b/skills/sqlite/references/wal-checkpointing.md @@ -0,0 +1,49 @@ +--- +title: SQLite WAL and Checkpointing +description: WAL mode setup, checkpoint strategy, and durability trade-offs +tags: sqlite, wal, checkpoint, durability, operations +--- + +# SQLite WAL and Checkpointing + +## Recommended baseline + +```sql +PRAGMA journal_mode = WAL; +PRAGMA synchronous = NORMAL; +``` + +- `WAL` improves read/write concurrency for most app workloads. +- `NORMAL` is a common balance; use `FULL` when durability requirements are strict. + +## Checkpoint behavior + +Checkpoint moves WAL pages back into the main database file. + +```sql +PRAGMA wal_checkpoint(PASSIVE); +PRAGMA wal_checkpoint(TRUNCATE); +``` + +- `PASSIVE` avoids blocking writers. +- `TRUNCATE` aggressively shrinks the WAL file when safe. + +## Autocheckpoint tuning + +```sql +PRAGMA wal_autocheckpoint = 1000; +``` + +- Default threshold is 1000 pages; tune using real write volume and latency goals. +- Too frequent checkpoints increase write amplification; too infrequent can bloat WAL. + +## Checkpoint mode selection + +- `PASSIVE`: best default for background maintenance; avoids blocking writers. +- `FULL`: waits for readers and writers as needed to complete more checkpoint work. +- `RESTART`/`TRUNCATE`: use for maintenance windows when you want WAL reset/shrink behavior. + +## Operational signals + +- WAL file grows without shrinking -> likely long readers or checkpoint starvation. +- Frequent sync stalls -> revisit transaction size, checkpoint cadence, and storage latency. diff --git a/website/index.html b/website/index.html index 37a341c..606c335 100644 --- a/website/index.html +++ b/website/index.html @@ -4,16 +4,16 @@ Database Skills — AI Agent Skills for Databases by PlanetScale - + - + - + @@ -641,7 +641,7 @@

Database Skills for AI Agents

- Make your agents smarter when working with Postgres, MySQL, Vitess, and Neki databases. + Make your agents smarter when working with Postgres, MySQL, SQLite, Vitess, and Neki databases.

@@ -698,6 +698,18 @@ + +
+ SQLite +
+
+
sqlite
+
planetscale/database-skills
+

SQLite is an embedded SQL database engine in a single file, ideal for local-first apps, edge workloads, and mobile clients that need reliable transactional storage.

+
+ +
+
Neki @@ -743,6 +755,9 @@ ├── vitess/ │ ├── SKILL.md │ └── references/ + ├── sqlite/ + │ ├── SKILL.md + │ └── references/ └── neki/ ├── SKILL.md └── references/ diff --git a/website/sqlite.svg b/website/sqlite.svg new file mode 100644 index 0000000..c9402a6 --- /dev/null +++ b/website/sqlite.svg @@ -0,0 +1,6 @@ + + + + + +