What a schema declares
Declare a table once
Apply it and atlantis writes the migration. tide generate writes the typed client.
entity Order in shop {
id bigint primary serial
customer_id varchar(8) not null references shop.Customer.id
total numeric(10, 2) not null
created_at timestamptz not null default now()
}Rehearse against real rows
Atlantis clones the real database and runs your migration against it. A migration your rows would break fails here, not in production.
tide rehearse
tide apply --wait-for-approval=30mRun work in the background
Retries and timeouts live in the schema. The handler stays in your own service.
job ImportContacts in directory {
args {
account_id varchar(64) not null
import_strategy varchar(20) not null default "skip"
}
retries 3
timeout 30m
queue "contacts"
visible_to "directory"
}Write your own SQL
Write the SQL the predicate language cannot express. touches() keeps the cache correct.
query NoteCountByMonth for Note {
input { since: timestamptz }
output { month: timestamptz, count: bigint }
sql touches(Note) {
SELECT date_trunc('month', created_at) AS month,
COUNT(*) AS count
FROM app.note
WHERE created_at >= $since
GROUP BY 1
ORDER BY 1
}
}Expire rows automatically
Name a timestamptz column and atlantis deletes expired rows every five minutes.
entity Session in consumer {
id varchar(8) primary
consumer_id varchar(8) not null references consumer.Account.id
session_token varchar(255) not null unique
expires_at timestamptz not null
created_at timestamptz not null default now()
ttl_field expires_at
}