Updated for nself v1.0.12
ɳSelf uses a schema-first approach with DBML (Database Markup Language) for designing, managing, and evolving your database schema with automatic migration generation.
nself v1.0.12 provides complete schema tools through the nself db command suite. Design your schema visually at dbdiagram.io, write migrations from your DBML design, and use nself db schema diagram to reverse-engineer an existing database.
Your schema is defined in schema.dbml file:
// Example schema.dbml
Project nself_project {
database_type: 'PostgreSQL'
Note: 'nself project database schema'
}
Table users {
id uuid [pk, default: `gen_random_uuid()`]
email varchar(255) [unique, not null]
name varchar(255) [not null]
password_hash varchar(255) [not null]
email_verified boolean [default: false]
created_at timestamp [default: `now()`, not null]
updated_at timestamp [default: `now()`, not null]
Note: 'User accounts and authentication'
}
Table profiles {
id uuid [pk, default: `gen_random_uuid()`]
user_id uuid [ref: > users.id, not null]
first_name varchar(100)
last_name varchar(100)
avatar_url varchar(500)
bio text
created_at timestamp [default: `now()`, not null]
updated_at timestamp [default: `now()`, not null]
}
Table posts {
id uuid [pk, default: `gen_random_uuid()`]
user_id uuid [ref: > users.id, not null]
title varchar(255) [not null]
content text
status post_status [default: 'draft']
published_at timestamp
created_at timestamp [default: `now()`, not null]
updated_at timestamp [default: `now()`, not null]
indexes {
user_id
status
(user_id, status)
published_at [where: 'published_at IS NOT NULL']
}
}
Enum post_status {
draft
published
archived
}# 1. Create a migration file for your schema
nself db migrate create basic_schema
# 2. Edit the generated .up.sql (or design in dbdiagram.io and paste SQL)
# 3. Apply migrations and seed:
nself db migrate up
nself db seed# Create a new migration (name it after the change)
nself db migrate create <name>
# Apply pending migrations
nself db migrate up
# Rollback last migration
nself db migrate down# Show current schema
nself db schema
# Show specific table schema
nself db schema show users
# Compare schema between environments
nself db schema diff staging
# Generate DBML from database (reverse engineer)
nself db schema diagram
# Export schema to SQL file
nself db schema export > schema.sql# Analyze and suggest indexes
nself db schema indexes
# Example output:
# Index Recommendations
# ─────────────────────
# [HIGH] orders.user_id - Frequently joined, no index
# [MEDIUM] products.category_id - Used in WHERE clauses
# [LOW] users.created_at - Occasional range queriesTable table_name {
id uuid [pk, default: `gen_random_uuid()`]
name varchar(255) [not null, unique]
email varchar(255) [not null, note: 'User email address']
age integer [default: 0]
created_at timestamp [default: `now()`]
// Table-level note
Note: 'Description of this table'
}pk - Primary keynot null - Not null constraintunique - Unique constraintdefault: value - Default valueincrement - Auto incrementnote: 'description' - Column documentationTable users {
id uuid [pk]
email varchar(255)
}
Table posts {
id uuid [pk]
user_id uuid [ref: > users.id] // Many-to-one relationship
title varchar(255)
}
// Alternative relationship syntax
Ref: posts.user_id > users.id
// One-to-many relationship
Ref: users.id < posts.user_id
// Many-to-many relationship
Ref: posts.id <> tags.idTable posts {
id uuid [pk]
user_id uuid
title varchar(255)
status varchar(50)
created_at timestamp
indexes {
user_id // Simple index
(user_id, status) // Composite index
title [type: hash] // Hash index
created_at [type: btree] // B-tree index
status [where: 'status != "draft"'] // Partial index
title [unique] // Unique index
}
}Enum user_role {
admin
moderator
user
guest
}
Enum post_status {
draft [note: 'Draft posts not visible to public']
published
archived
deleted
}
Table users {
role user_role [default: 'user']
status user_status [not null]
}Create migrations for common schema patterns:
nself db migrate create basic_schema
# Edit the generated file to add: users, profiles, postsnself db migrate create ecommerce_schema
# Edit the generated file to add: users, products, categories, orders, order_items, cart_itemsnself db migrate create saas_schema
# Edit the generated file to add: organizations, users, organization_members, invitations, projects, api_keysnself db migrate create blog_schema
# Edit the generated file to add: users, posts, categories, tags, post_categories, post_tags, comments, mediaDesign your schema visually at dbdiagram.io, then create a migration:
# Create a migration for your DBML design
nself db migrate create imported_schema
# This creates:
# nself/migrations/20260122_imported_schema.up.sql
# nself/migrations/20260122_imported_schema.down.sql
# Fill the .up.sql with your schema SQL, then run: nself db migrate upGenerate DBML from your existing database:
nself db schema diagram > schema.dbml
# Open the generated file at dbdiagram.io to visualize// Before
Table users {
id uuid [pk]
email varchar(255)
name varchar(255)
}
// After - Adding phone column
Table users {
id uuid [pk]
email varchar(255)
name varchar(255)
phone varchar(20)
created_at timestamp [default: `now()`]
}// Before
Table users {
name varchar(100)
}
// After - Increase length and add constraint
Table users {
name varchar(255) [not null]
}// Before - Standalone tables
Table users {
id uuid [pk]
}
Table posts {
id uuid [pk]
title varchar(255)
}
// After - Adding relationship
Table posts {
id uuid [pk]
user_id uuid [ref: > users.id]
title varchar(255)
}Table tenants {
id uuid [pk]
name varchar(255) [not null]
subdomain varchar(50) [unique, not null]
created_at timestamp [default: `now()`]
}
Table users {
id uuid [pk]
tenant_id uuid [ref: > tenants.id, not null]
email varchar(255) [not null]
name varchar(255)
// Ensure email uniqueness within tenant
indexes {
(tenant_id, email) [unique]
}
}
Table posts {
id uuid [pk]
tenant_id uuid [ref: > tenants.id, not null]
user_id uuid [ref: > users.id, not null]
title varchar(255)
// Row Level Security policies will be applied
Note: 'Posts are isolated by tenant'
}Table audit_log {
id uuid [pk, default: `gen_random_uuid()`]
table_name varchar(100) [not null]
record_id uuid [not null]
action audit_action [not null]
old_values jsonb
new_values jsonb
user_id uuid [ref: > users.id]
timestamp timestamp [default: `now()`, not null]
indexes {
table_name
record_id
user_id
timestamp
(table_name, record_id)
}
}
Enum audit_action {
INSERT
UPDATE
DELETE
}Apply a complete workflow from DBML to working database:
nself db migrate up schema.dbmlThis automatically:
Compare your local schema with another environment:
nself db schema diff staging
# Example output:
# Schema Differences (local vs staging)
# ────────────────────────────────────
# + Table: user_preferences (missing in staging)
# ~ Column: users.last_login (different type)
# - Index: idx_orders_date (missing in local)Generate typed interfaces from your database schema:
# Generate TypeScript types
nself db types typescript
# Generate Go structs
nself db types go
# Generate Python dataclasses
nself db types python
# Generate to specific directory
nself db types typescript --output src/types/
# Include comments
nself db types typescript --comments# Problem: Import fails with parse error
# Solution: Check DBML syntax:
# - Column names must be valid identifiers
# - Types must be supported
# - Brackets must be balanced
# Validate at dbdiagram.io before importing# Check status and repair if needed
nself db migrate status
nself db migrate repair # Fix tracking table# Rollback last migration
nself db migrate down
# Rollback specific number of migrations
nself db migrate down 2
# Restore from backup if needed
nself db restore# Schema commands (v1.0.0)
nself db schema # Show current schema
nself db migrate create basic # Create from template
nself db migrate create file.dbml # DBML to SQL migration
nself db migrate up file.dbml # Import + migrate + seed
nself db schema diagram # Database to DBML
nself db schema diff staging # Compare schemas
nself db schema show users # Show table schema
nself db schema indexes # Suggest indexes
nself db schema export # Export to SQL
# Type generation
nself db types typescript # Generate TS types
nself db types go # Generate Go structs
nself db types python # Generate Python types