Skip to content
Data Model

Data Model

DataKit uses two closely related models:

  • package manifests define the logical package and its data dependencies
  • controller CRDs define deployed state inside Kubernetes

Data Model

Manifest Kinds and Relationships

The core manifest graph is derived, not separately declared.

KindPurposeKey relationship
ConnectorTechnology type such as Postgres, S3, or KafkaStore.spec.connector points at the connector provider identity
StoreNamed infrastructure instance plus connection data and secretsa DataSet lives in exactly one store
DataSetData contract for a table, prefix, or topicTransform inputs and outputs reference datasets by name
DataSetGroupBundle of multiple datasets from one materializationgroups dataset names under one store
TransformExecutable computation unitconsumes input datasets and produces output datasets
SemanticProjectSemantic-layer package rootreferences semantic models and produces semantic deployment artifacts

The default dependency chain is:

Connector -> Store -> DataSet -> Transform

Important implications:

  • there is no pipeline.yaml
  • the pipeline graph is derived from Transform.spec.inputs and Transform.spec.outputs
  • stores hold secrets and connection details; datasets and transforms do not
  • cell selection changes how logical names resolve to physical infrastructure, not the logical graph itself

PackageDeployment CRD

PackageDeployment is the controller’s execution intent object. It links an OCI package reference to a target cell and an execution mode.

Spec

FieldMeaning
spec.packageOCI package reference: name, namespace, version, registry, optional digest
spec.celltarget Cell name; controller resolves the cell to a Kubernetes namespace
spec.modebatch, streaming, or semantic
spec.schedulecron schedule for recurring batch runs
spec.replicasdesired replica count for streaming mode
spec.timeoutmax run duration for batch mode
spec.resourcesCPU and memory requests/limits
spec.serviceAccountNamepod service account
spec.imagePullSecretsregistry auth secrets
spec.envdeploy-time environment overrides

Status

FieldMeaning
status.phasePending, Pulling, Ready, Running, Completed, Failed
status.conditionsdetailed controller observations
status.packageresolved OCI digest and fully qualified reference
status.lastRunrun id, start/end times, result, records processed
status.failureCountconsecutive workload failures
status.pullRetryCountconsecutive pull failures
status.observedGenerationlast reconciled spec generation

ClickHouseMigration Lifecycle

ClickHouseMigration does not use an explicit phase enum. Its lifecycle is inferred from status and conditions.

Conceptual stateObserved fields
PendingCR exists, status.applied=false, required dependencies may not be satisfied yet
Runningcontroller is actively resolving stores, secrets, env vars, or executing DDL
Completedstatus.applied=true, status.appliedAt set, Applied=True, Ready=True
Failedstatus.applied=false, with conditions such as StoreResolutionFailed, EnvResolutionFailed, or ExecutionFailed

Additional lifecycle rules:

  • migrations are ordered within the same store + database scope using spec.order
  • the applied SQL hash includes both SQL text and envFrom, so changing either triggers re-application
  • deleting the CR does not drop tables; deletion is intentionally a no-op for safety

CRD Relationships

Inside the cluster, the main controller-side relationships are:

  • Cell maps a logical deployment target to a Kubernetes namespace
  • Store and DataSet live in that namespace
  • PackageDeployment.spec.cell selects the namespace where stores resolve and workloads run
  • ClickHouseMigration.spec.store binds DDL execution to a store in the same namespace

That means the same logical package can be promoted to different cells while resolving different physical stores.

Validation Error Codes

Validation is split between generic validator helpers and kind-specific manifest rules. The most important architecture-level codes are below.

CodeMeaning
E001metadata name is not DNS-safe
E020version is not valid SemVer
E040spec.runtime is required
E041spec.image is required for generic runtimes
E200connector type is required
E210store connector is required
E211store connection must be non-empty
E220dataset store is required
E221dataset location is required
E222dataset schema is invalid
E230transform inputs must be non-empty
E231transform outputs must be non-empty
E232transform image is required for generic runtimes
E240dataset group store is required
E241dataset group must list datasets
E310schemaRef and inline schema are mutually exclusive
E311schemaRef format is invalid
E312schema lock entry is missing
E313schema lock checksum failed
E314breaking schema change detected

Entity Lifecycle

The data model becomes runtime state in stages:

  1. Manifests define logical intent (Connector, Store, DataSet, Transform)
  2. OCI packages preserve that intent as immutable artifacts
  3. PackageDeployment binds a package to an environment and cell
  4. The controller translates that binding into Kubernetes-native execution objects

See the Service Architecture — Reconciliation Loop for the full sequence diagram of this lifecycle.

In other words:

  1. manifests define logical intent
  2. OCI packages preserve that intent as immutable artifacts
  3. PackageDeployment binds a package to an environment and cell
  4. the controller translates that binding into Kubernetes-native execution objects
  5. status fields become the durable runtime record for operators

See Also