About database-patterns
A database-patterns reference for developers working with SQL migrations and Exposed. It covers schema conventions, entities, repositories, and table-creation steps.
Key features
- 01Standard columns and UUID keys
- 02Soft deletes and partial indexes
- 03Exposed table and entity patterns
- 04Repository interfaces and read/write split
- 05Flyway migration and table checklist
Use cases
- 01Create a table following project conventions
- 02Implement repository access for soft-deleted data
- 03Write sequential, focused Flyway migrations
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ c0x12c/ ai-toolkit --skill database-patternsAfter installing, type/database-patternsin Claude Code to confirm it loaded.
Bundled filescode-templates.md
Details
From the project READMEDatabase Patterns — Quick Reference
Hard Rules
| Rule | Do | Don't |
|---|---|---|
| Data types | TEXT | VARCHAR |
| Primary keys | UUID | SERIAL, BIGINT |
| Soft delete | deleted_at TIMESTAMP | DELETE FROM |
| Foreign keys | App-level validation | REFERENCES, ON DELETE CASCADE |
| Standard columns | id, created_at, updated_at, deleted_at | Skip any of these |
Migration Template
SQL migration with table, trigger, and partial indexes for soft delete.
See code-templates.md for the complete SQL template.
Exposed Table Object
Extend UUIDTable, use text() not varchar(), add standard timestamp columns.
See code-templates.md for the complete template.
Entity Data Class
Implement Entity<Instant>, include all business fields + createdAt, updatedAt, deletedAt.
See code-templates.md for the complete template.
Repository Pattern
Interface + Default* implementation. Reads on db.replica, writes on db.primary. Soft delete via deletedAt update. convert() method maps ResultRow to entity.
See code-templates.md for the full interface + implementation code.
When Creating a New Table
Full checklist:
- SQL migration file (next number in sequence)
- Table object in
module-repository/table/ - Entity data class in
module-repository/entity/ - Enum/constants in
module-repository/constant/(if needed) - Repository interface + implementation
- Factory bean for repository
- Repository tests
Flyway Rules
- NEVER add a migration that fills a gap in deployed sequence
- NEVER rename an already-deployed migration file
- Migration numbers must be sequential from the latest
- Keep migrations simple and focused (one table per migration)
Gotchas
- Only
iduses.value-- everything else is direct.row[Table.id].valuegives UUID, butrow[Table.projectId]already returns UUID. Adding.valueto non-id columns causes compile errors. gen_random_uuid()vsuuid_generate_v4()-- pick one per project. Mixing them works but confuses code review. Check existing migrations for which one the project uses.- Don't re-declare
createdAt,updatedAt,deletedAtif extending SoftDeleteTable. They're inherited. Declaring them again causes duplicate column errors. - Forgetting
WHERE deleted_at IS NULLon indexes wastes space. Every index on a soft-delete table should be partial. Full indexes include dead records nobody queries. - Text columns that hold JSON should still use
text()in Exposed. JSONB in Postgres,text()in Kotlin, serialize/deserialize in the entity layer.