See it as a diagram
Everything below, as a diagram you can edit. Describe yours and see it in seconds.
No account needed · Editable canvas, not a picture
The four things that ship together
Code: ingestion, transformation, and the tests that guard the output. It lives in the domain repository, is reviewed by the domain, and deploys through the domain pipeline.
Data: the actual bytes, in whatever storage the platform provides, along with the retention window that has been promised.
Metadata: schema, semantics, owner, classification, lineage, and the contract. Metadata that lives only in a wiki page belongs to nobody; metadata that ships with the product gets updated when the product changes.
Infrastructure: the compute, storage, and access policy the product needs, declared as code so the product can be redeployed rather than reconstructed. Bundling infrastructure is what makes a data product portable between accounts, which matters the first time a domain moves.
Ports: the only supported way in and out
An input port declares where the product reads from and in what format. Naming input ports is what turns a hidden dependency into a documented one, and it is the difference between a lineage graph you generate and a lineage graph you guess.
An output port is the product API: read-only access to a dataset in a specific technology and protocol. One product can offer several, and the common pattern is more than one shape of the same data, for example a warehouse table for analysts, a topic for services, and a redacted variant with PII removed for a wider audience. Each port has its own schema and its own access policy.
The rule that makes this worth doing: nothing outside the domain reads anything except through a declared output port. A consumer reading the product's internal staging table has taken a dependency nobody agreed to, and the producer will break it on the next refactor without knowing.
DATSIS: the checklist a product has to pass
DATSIS is the community acronym for the six section headings under "Domain data as a product" in Dehghani's 2019 article: discoverable, addressable, trustworthy and truthful, self-describing semantics and syntax, inter-operable and governed by global standards, secure and governed by a global access control. The acronym is not hers; the six are. It is a checklist rather than a philosophy, and it is short enough to run in a review.
Discoverable means registered in the catalog, findable by someone who does not know it exists. Addressable means a stable, permanent address that survives a refactor. Trustworthy means the quality checks and the service level are published and measured, not asserted. Self-describing means schema and semantics arrive with the data, so nobody has to ask the owner what status = 3 means. Interoperable means the join keys and the classification vocabulary match the global standards, which is exactly what federated governance exists to set. Secure means access control is enforced at the port, per port.
Later restatements add "valuable on its own" and "natively accessible", which are worth knowing but are not in the original six. A product failing any of the six above fails in a way consumers feel within a week; a product failing only the later two is merely less useful than it could be.
Versioning, deprecating, and the picture that keeps up
Version the output port schema, not just the code. Additive changes go out as a minor version; a removed or retyped column is a new major version, published alongside the old one for the notice period written into the contract. Deprecation is an announced date plus a way for the producer to see who is still reading, which is why lineage down to the column matters here rather than at audit time.
A domain that publishes five products with three ports each has fifteen interfaces and an architecture worth drawing once. Datadef generates the canvas from a description, keeps column-level lineage between products, and regenerates from the connected repository on a daily sync so the picture matches the branch the domain actually ships. Because node identity is derived from the source rather than assigned per run, adding a sixth product reads as one new node instead of a new drawing.
# The ports declared, so the dependency graph is read rather than guessed.
# dbt meta on the published model; the contract carries the promises.
models:
- name: orders_fct
description: One row per confirmed order, checkout domain vocabulary.
meta:
domain: checkout
data_product: orders
owner: [email protected]
input_ports:
- postgres://checkout-prod/public/orders
- s3://acme-events/checkout/payments/
output_ports:
- id: warehouse
address: snowflake://analytics/checkout/orders_fct
audience: analysts
- id: stream
address: kafka://checkout.orders.v2
audience: services
- id: redacted
address: snowflake://analytics/checkout/orders_fct_public
audience: everyone
pii: removed
contract: contracts/checkout/orders.odcs.yamlFAQ
What is a data product in a data mesh?
What is the difference between a data product and a table?
What is an output port?
What does DATSIS stand for?
How do you deprecate a data product without breaking consumers?