Four Requests, One Schema, Nothing Retyped
Here is a realistic week for whoever owns the customer schema in a mid-sized data platform.
Four Requests, One Schema, Nothing Retyped
Here is a realistic week for whoever owns the customer schema in a mid-sized data platform.
The platform team is standing up a new service and needs the customer tables in SQL Server. The streaming team wants a record definition for a topic. A partner's procurement process asks for a machine-readable data contract before they will sign. And on Thursday somebody asks, in a channel, what the legal values of status are.
Historically those are four separate pieces of work, done by three people, producing four artifacts that will disagree within a quarter. This article is about what each looks like after a team has adopted SQL DDL as a governed format rather than a hand-maintained one.
The entry ticket is one POST
Adoption starts with the DDL you already have. A schema import call takes the format key sql and the CREATE TABLE text, and returns a governed model: a Type per table, an Element per column, required flags wherever the DDL said NOT NULL, real references between Types wherever there were foreign keys, and a governed vocabulary wherever a MySQL ENUM column had been quietly enforcing a list for years. The response carries a lossiness report — the honest list of anything the model could not hold, such as a UNIQUE or CHECK constraint. On a clean table that list is empty.
Nothing runs inside your database. No credentials are exchanged. The input is a text artifact your schema tooling already produces.
Request one: the same tables, a different engine
The platform team's request stops being a porting exercise and becomes a parameter. The schema export call takes a vendor option — postgres by default, or mysql, or sqlserver — and commits fully to that dialect.
Identifiers come out double-quoted, backticked, or bracketed. A boolean Element is emitted as BOOLEAN, TINYINT(1), or BIT; a date-time as TIMESTAMP, DATETIME, or DATETIME2; text lands as NVARCHAR(255) on SQL Server and VARCHAR(255) elsewhere. A project stores the modeled type rather than the source spelling, so these vendor-idiomatic types are what a project export emits; on the stateless conversion route, a column that arrived as SQL keeps its exact original type text — a VARCHAR(42) is re-emitted as a VARCHAR(42), not widened to a default. Foreign keys come back as REFERENCES clauses pointing at the target table.
Where a dialect genuinely cannot express something, the export says so rather than pretending. A governed vocabulary becomes an inline ENUM list on MySQL; on PostgreSQL and SQL Server it becomes a VARCHAR with a recorded note that the allowed-value constraint is not enforced there. You know, per artifact, exactly which guarantees you are shipping.
Request two: the schema leaves the relational world
The streaming team's request used to mean reading DDL and hand-writing a record schema, which is where enums evaporate and optionality flips. Now SQL is one door into a model with many doors out. The same project exports as JSON Schema, Avro, JSON-LD, ShEx, OWL, LinkML, Protobuf, an ODCS data contract, or an Apache Ossie/OSI semantic model — each with its own honest account of what that format could not carry.
The important word is generated. The Avro the streaming team receives and the DDL the platform team receives are provably describing the same thing, because both came out of the same governed definition on the same afternoon. Nobody has to reconcile them later, because there is nothing to reconcile.
Request three: the contract the partner asked for
The partner's data contract is the same export with a different target format. What makes it defensible rather than decorative is that nobody typed it while reading a table: it was derived from the same model the DDL and the streaming schema came from. When the model changes, all of those artifacts are regenerated, and the differences show up in a diff instead of in an incident.
Request four: what the status values are
This is the one that quietly changes the most.
Before, status was a VARCHAR and the answer was whatever the most confident person in the channel said. After, it is a governed vocabulary with named terms, each of which can carry a description — and each column can carry a mapping to a public vocabulary term, so "our full_name" and "their customerName" can be stated to be the same concept rather than argued about.
The part that surprises people is that this survives the trip back into SQL. DDL has no annotation slot, so on export we use the one place SQL allows: column comments. Semantic annotations are written as a small machine-readable object — inline COMMENT syntax on MySQL, standalone COMMENT ON COLUMN statements for PostgreSQL and SQL Server. Re-import that DDL later and the annotations lift straight back out of the comments into the model. The meaning commutes. It is not a side-channel that evaporates the first time the schema touches a database.
Records move too
Structure is the common case, but rows travel on the same rails. The data side of the transform surface reads and writes records as JSON, CSV, JSON-LD, Avro — or as SQL INSERT statements, guided by the project's own schema. Seeding a test environment from a governed sample stops being a bespoke script.
What has actually changed
The visible win is time. The structural win is direction.
- Before: the schema exists in three dialects, each maintained by hand, each drifting on its own schedule. After: it exists once, and dialects are outputs you regenerate.
- Before: "which is right, the DDL or the documentation?" After: the documentation is generated, so the question is malformed.
- Before: each new consumer re-derives the schema by hand and introduces its own small distortions. After: each consumer exports its native format from the same source.
- Before: you learn what a conversion dropped when something breaks downstream. After: every conversion hands you a ledger of what it could not carry, up front, per element.
- Before: meaning lives beside the schema, in prose that nobody regenerates. After: meaning lives on the schema and rides inside the SQL itself.
None of this required a migration project, new infrastructure, or a database connection. Writes are role-gated; reads are safe to automate; applying anything to a real database stays in your change-management path, reviewed the way you already review schema changes.
The schema owner's week does not become empty. It becomes a week of decisions about meaning instead of an afternoon of retyping TINYINT(1).
If you want to run this loop yourself, the Schema Transformation quickstart in the CoreModels docs walks import, annotate, and export end to end against a scratch project.