Loading...
Loading...
Patterns for Atlas database schema management covering HCL/SQL schema definitions, versioned and declarative migrations, linting analyzers, testing, and project configuration. Use when working with atlas.hcl, .hcl schema files, Atlas CLI commands, or database migrations.
npx skill4agent add 0xbigboss/claude-code atlas-best-practicesatlas schema apply --url "postgres://..." --to "file://schema.hcl" --dev-url "docker://postgres/15"atlas migrate diff add_users --dir "file://migrations" --to "file://schema.sql" --dev-url "docker://postgres/15"
atlas migrate apply --dir "file://migrations" --url "postgres://..."# PostgreSQL
--dev-url "docker://postgres/15/dev?search_path=public"
# MySQL
--dev-url "docker://mysql/8/dev"
# SQLite
--dev-url "sqlite://dev?mode=memory".pg.hcl.my.hcl.lt.hclschema "public" {
comment = "Application schema"
}
table "users" {
schema = schema.public
column "id" {
type = bigint
}
column "email" {
type = varchar(255)
null = false
}
column "created_at" {
type = timestamptz
default = sql("now()")
}
primary_key {
columns = [column.id]
}
index "idx_users_email" {
columns = [column.email]
unique = true
}
}
table "orders" {
schema = schema.public
column "id" {
type = bigint
}
column "user_id" {
type = bigint
null = false
}
column "total" {
type = numeric
null = false
}
foreign_key "fk_user" {
columns = [column.user_id]
ref_columns = [table.users.column.id]
on_delete = CASCADE
}
check "positive_total" {
expr = "total > 0"
}
}CREATE TABLE "users" (
"id" bigint PRIMARY KEY,
"email" varchar(255) NOT NULL UNIQUE,
"created_at" timestamptz DEFAULT now()
);atlas.hclvariable "db_url" {
type = string
}
env "local" {
src = "file://schema.pg.hcl"
url = var.db_url
dev = "docker://postgres/15/dev?search_path=public"
migration {
dir = "file://migrations"
}
format {
migrate {
diff = "{{ sql . \" \" }}"
}
}
}
env "prod" {
src = "file://schema.pg.hcl"
url = var.db_url
migration {
dir = "atlas://myapp" # Atlas Registry
}
}atlas schema apply --env local --var "db_url=postgres://..."atlas.hcllint {
destructive {
error = true # Fail on DROP TABLE/COLUMN
}
data_depend {
error = true # Fail on data-dependent changes
}
naming {
match = "^[a-z_]+$"
message = "must be lowercase with underscores"
index {
match = "^idx_"
message = "indexes must start with idx_"
}
}
# PostgreSQL: require CONCURRENTLY for indexes (Pro)
concurrent_index {
error = true
}
}atlas migrate lint --env local --latest 1-- atlas:nolint destructive
DROP TABLE old_users;.test.hcltest "schema" "user_constraints" {
parallel = true
exec {
sql = "INSERT INTO users (id, email) VALUES (1, 'test@example.com')"
}
# Test unique constraint
catch {
sql = "INSERT INTO users (id, email) VALUES (2, 'test@example.com')"
error = "duplicate key"
}
assert {
sql = "SELECT COUNT(*) = 1 FROM users"
error_message = "expected exactly one user"
}
cleanup {
sql = "DELETE FROM users"
}
}
# Table-driven tests
test "schema" "email_validation" {
for_each = [
{input: "valid@test.com", valid: true},
{input: "invalid", valid: false},
]
exec {
sql = "SELECT validate_email('${each.value.input}')"
output = each.value.valid ? "t" : "f"
}
}atlas schema test --env local schema.test.hcl-- atlas:txmode none
CREATE INDEX CONCURRENTLY idx_users_email ON users (email);fileallnoneatlas.hclenv "prod" {
check "migrate_apply" {
deny "too_many_files" {
condition = length(self.planned_migration.files) > 3
message = "Cannot apply more than 3 migrations at once"
}
}
}# Generate migration from schema diff
atlas migrate diff migration_name --env local
# Apply pending migrations
atlas migrate apply --env local
# Validate migration directory integrity
atlas migrate validate --env local
# View migration status
atlas migrate status --env local
# Push to Atlas Registry
atlas migrate push myapp --env local
# Declarative apply (no migration files)
atlas schema apply --env local --auto-approve
# Inspect current database schema
atlas schema inspect --url "postgres://..." --format "{{ sql . }}"
# Compare schemas
atlas schema diff --from "postgres://..." --to "file://schema.hcl"- uses: ariga/setup-atlas@v0
with:
cloud-token: ${{ secrets.ATLAS_CLOUD_TOKEN }}
- name: Lint migrations
run: atlas migrate lint --env ci --git-base origin/main# Create baseline migration reflecting current schema
atlas migrate diff baseline --env local --to "file://schema.hcl"
# Mark baseline as applied (skip execution)
atlas migrate apply --env prod --baseline "20240101000000"data "external_schema" "gorm" {
program = [
"go", "run", "-mod=mod",
"ariga.io/atlas-provider-gorm",
"load", "--path", "./models",
"--dialect", "postgres",
]
}
env "local" {
src = data.external_schema.gorm.url
}migrate diffschema apply.test.hcl-- atlas:txmode none