A schema names a logical group of models:
schema seaport
model Booking {
id: int
}Schemas are used by model registration, DDL generation, migration selection, and datasource routing.
The declaration is compile-time metadata. It does not create a module
namespace, import binding, or runtime value named seaport.
Current scope
The current compiler records schema NAME for models in the same compilation
unit. The older directory convention—placing schema.at in a directory to
claim every model below it—is not yet a complete project-level guarantee.
Until that propagation lands, keep a schema declaration with the models whose association must be unambiguous and confirm the generated schema snapshot.
When several source units contribute models, inspect the compiler’s registered model metadata rather than assuming a declaration in one directory implicitly flows to every descendant.
Not a module
A schema and a module solve different problems:
| Concept | Controls |
|---|---|
| Module | Names, imports, and source-file organization |
| Schema | Persisted model grouping and data tooling |
| Datasource | Engine, connection, and query route |
One module can use models from several schemas. A schema can be routed to different engines between deployments. Neither fact changes import syntax.
The same source model names can also live in different modules, but database table naming still needs to remain unambiguous within the generated schema.
Data boundaries
The intended design uses schemas for migration and join boundaries. Current transaction checking is stricter and more operational: all queries in a transaction must resolve to one datasource route. Schema-scoped join rejection is not fully enforced, so successful compilation alone should not be treated as a cross-schema data architecture policy.
Use explicit service or repository boundaries when cross-schema access needs authorization, consistency, or deployment restrictions. A logical schema name is routing metadata, not an access-control mechanism.
Generated DDL
The compiler can build a schema snapshot from registered models and render
per-dialect CREATE TABLE, foreign-key, and index statements. Migration
diffing compares that desired snapshot with an introspected live database.
Because temporal and alias types currently follow wire-faithful storage mappings, reverse introspection recovers storage shape rather than every original domain type. Review generated migrations as database changes, not as a lossless source-code round trip.
Routing
[datasources.NAME].schema associates a configured engine with this logical
name. Query lowering selects the first matching route. With exactly one
configured datasource, models without a matching schema inherit that engine’s
dialect; with zero or multiple configured routes, unmatched models use the
SQLite compatibility default.
That fallback keeps unconfigured tests working but is not a substitute for an explicit production route.