DevMatrixDMX Language Reference
Back to Workshop
Language Reference

DMX Specification Language

The complete reference for writing DevMatrix specifications. From data types and annotations to flows, state machines, and infrastructure.

Overview

DMX (DevMatrix Specification Language) is a declarative language for defining full-stack microservices. A single .dmx file describes entities, APIs, business flows, state machines, security, infrastructure, and more — then compiles deterministically to production-ready code. DMX is not a template engine. It is a compiler IR: every construct maps to concrete backend code through deterministic passes. There is no interpolation, no scripting, and no runtime interpretation.

Lexical Structure

DMX source files use UTF-8 encoding. The language is whitespace-insensitive (indentation is conventional, not syntactic). Blocks are delimited by curly braces {}.

Comments

Line comments start with //. Block comments use /* ... */.
Comments
// This is a line comment

/* This is a
   block comment */

Strings

Strings are double-quoted only. Backslash escapes are supported: \", \\, \n.

Numbers

Integer literals: 42, 0. Float literals: 3.14. No hex/octal support.

Identifiers

PascalCase for entities and types (UserProfile). snake_case for fields and keywords (created_at). UPPER_SNAKE_CASE for enum values (ACTIVE, PENDING_REVIEW).

Operators

= — assignment. -> — state transition or mapping. * — wildcard/all.

Annotations

Annotations start with @ followed by an identifier. Some accept parenthesized arguments: @default("active"), @fk(User.id).

Dollar Tokens

Runtime references prefixed with $. Simple: $input, $context. Dotted: $computed.now, $input.email.

Data Types

DMX supports 18 data types that map to database column types and API schema types.

NameDescription
UUIDUniversally unique identifier (v4)
StringVariable-length text, up to 255 characters
TextUnlimited-length text (CLOB/TEXT)
IntegerWhole number (32-bit signed)
FloatIEEE 754 floating-point
DecimalArbitrary-precision decimal
Booleantrue or false
DateCalendar date without time (YYYY-MM-DD)
DateTimeDate and time with timezone (ISO 8601)
TimeTime of day without date
JSONArbitrary JSON object or array
BytesBinary data (BLOB)
ArrayOrdered collection of a single type
EnumEnumerated set of named values
CharFixed-length character string
PointGeographic point (latitude, longitude)
PolygonGeographic polygon boundary
GeometryArbitrary geometric shape

Every entity field has a name, a type, and optional annotations.

Field declarations with types
entity User {
  id          UUID     @pk @default($computed.uuid)
  email       String   @unique @not_null
  name        String   @not_null
  bio         Text     @nullable
  age         Integer  @check("age >= 0")
  balance     Decimal  @default(0)
  is_active   Boolean  @default(true)
  joined_at   DateTime @default($computed.now)
  metadata    JSON     @nullable
  role        Enum(ADMIN, MEMBER, GUEST) @default(MEMBER)
  location    Point    @nullable
}

Annotations

Annotations modify the behavior of fields, entities, APIs, state machines, and ClickHouse columns.

Field Annotations

NameDescriptionSyntax
@pkPrimary key@pk
@not_nullNOT NULL constraint@not_null
@uniqueUnique constraint@unique
@nullableAllows NULL values@nullable
@defaultDefault value@default("value") or @default($computed.now)
@fkForeign key reference@fk(Entity.field)
@checkCheck constraint expression@check("age >= 18")
@requiredRequired in API input@required
@sensitivePII / secrets — excluded from logs@sensitive
@computedServer-computed, not in API input@computed
@json_listStore as JSON array column@json_list
@immutableCannot be updated after creation@immutable
@indexedCreate a database index@indexed

Entity Annotations

NameDescriptionSyntax
@aggregate_rootDDD aggregate root — owns child entities@aggregate_root
@tenancyTenant isolation strategy@tenancy("row") or @tenancy("schema")
@descriptionHuman-readable description@description("User accounts")
@auditAuto-generate created_at / updated_at / deleted_at@audit
@soft_deleteSoft delete (set deleted_at) instead of hard delete@soft_delete
@platform_scopeNot tenant-scoped (platform-level entity)@platform_scope
@append_onlyInsert-only table (no UPDATE or DELETE)@append_only
@append_only_afterAppend-only after a condition is met@append_only_after("status = CLOSED")
@unique_togetherComposite unique constraint@unique_together(field_a, field_b)
@checkEntity-level check constraint@check("start_date < end_date")
@relationDefine relationship to another entity@relation("has_many", Target)

API Annotations

NameDescriptionSyntax
@entityBind API to an entity@entity(User)
@paginatedEnable pagination@paginated
@statusOverride HTTP status code@status(201)
@triggersEmit events on action@triggers(user_created)

State Machine Annotations

NameDescriptionSyntax
@rolesRestrict transition to roles@roles(ADMIN, MANAGER)
@guardGuard condition for transition@guard("amount > 0")

ClickHouse Annotations

NameDescriptionSyntax
@low_cardinalityClickHouse LowCardinality optimization@low_cardinality
@piiMark column as PII for compliance@pii

Dollar Tokens ($)

Runtime value references used in defaults, flow steps, and computed fields. The compiler resolves these to actual code.

NameDescriptionSyntax
$inputCurrent request/step input data$input.email, $input.password
$contextExecution context (authenticated user, tenant, request metadata)$context.user_id, $context.tenant_id
$instanceCurrent entity instance (in flows and state machines)$instance.status, $instance.id
$resultResult from the previous flow step$result.id, $result.token
$computed.nowCurrent UTC timestamp@default($computed.now)
$computed.uuidGenerate a new UUID v4@default($computed.uuid)
$computed.hash_passwordHash a password with bcryptpassword = $computed.hash_password($input.password)
$computed.verify_hashVerify a bcrypt hash$computed.verify_hash($input.password, $instance.password)
$computed.hashGeneric SHA-256 hash$computed.hash($input.data)
$computed.sign_jwtSign a JWT token$computed.sign_jwt($instance.id, $instance.role)
$computed.decode_jwtDecode and verify a JWT token$computed.decode_jwt($input.token)
$computed.random_tokenGenerate a random token string$computed.random_token(32)
$computed.now_plus_hoursCurrent time plus N hours$computed.now_plus_hours(24)
$computed.now_plus_daysCurrent time plus N days$computed.now_plus_days(30)

Top-Level Blocks

DMX specs are composed of top-level blocks. Each block defines a different concern of the service.

service

The root block that defines a microservice. Contains all other blocks.
Service definition
service UserService {
  version = "1.0.0"
  port = 8000
  api_prefix = "/api/v1"
  database = "postgresql"

  // ... entities, api, flows, etc.
}

entity

Defines a data model. Fields have a name, type, and optional annotations. Entities compile to database tables, ORM models, and Pydantic schemas.
Entity with annotations
entity Order @audit @soft_delete {
  id          UUID      @pk @default($computed.uuid)
  customer_id UUID      @fk(Customer.id) @not_null
  total       Decimal   @not_null @check("total >= 0")
  status      Enum(DRAFT, PENDING, PAID, SHIPPED, CANCELLED) @default(DRAFT)
  notes       Text      @nullable
}

api

Defines REST, GraphQL, or WebSocket endpoints for an entity.
REST API
api REST @entity(Order) @paginated {
  // Standard CRUD endpoints are generated automatically
  // Custom endpoints:
  POST   "/orders/{id}/cancel"  @status(200) @triggers(order_cancelled)
  GET    "/orders/summary"      @roles(ADMIN)
}

flow

Multi-step business process. Each step has an action, target entity, and field mappings. Flows compile to service-layer functions with transaction management.
Registration flow
flow RegisterUser {
  step validate_input {
    action = validate
    target = User
    mapping {
      email = $input.email
      password = $input.password
    }
  }

  step create_user {
    action = create
    target = User
    mapping {
      id = $computed.uuid
      email = $input.email
      password = $computed.hash_password($input.password)
      created_at = $computed.now
    }
  }

  step generate_token {
    action = calculate
    expression = $computed.sign_jwt($result.id, $result.role)
    result_capture = "token"
  }
}

state_machine

Defines valid state transitions with guards and role restrictions. Compiles to a state machine implementation with validation.
Order state machine
state_machine OrderStatus {
  initial = DRAFT

  DRAFT -> PENDING @roles(MEMBER, ADMIN)
  PENDING -> PAID @guard("payment_confirmed == true")
  PAID -> SHIPPED @roles(ADMIN)
  SHIPPED -> DELIVERED
  PENDING -> CANCELLED @roles(MEMBER, ADMIN)
  DRAFT -> CANCELLED
}

validations

Validation rules applied to entity fields. Compile to both database constraints and API-level validation.
Validation rules
validations {
  email {
    format = "email"
    uniqueness = true
  }
  age {
    range = "0..150"
    presence = true
  }
  username {
    format = "^[a-zA-Z0-9_]{3,30}$"
    uniqueness = true
  }
}

security

Authentication, authorization, rate limiting, and password policies.
Security configuration
security {
  auth_scheme = "jwt"
  jwt_algorithm = "HS256"
  token_expiry_minutes = 60
  refresh_token_enabled = true
  password_hashing = "bcrypt"

  rate_limit {
    policy = "sliding_window"
    allow = 100
    for = "1m"
  }

  roles = [ADMIN, MEMBER, GUEST]
}

errors

Custom error definitions with HTTP status codes, categories, and messages.
Error definitions
errors {
  USER_NOT_FOUND {
    status = 404
    category = "not_found"
    message = "User not found"
  }
  INVALID_CREDENTIALS {
    status = 401
    category = "auth"
    message = "Invalid email or password"
  }
}

jobs

Background job definitions with scheduling, retry policies, and queue configuration.
Job definitions
jobs {
  cleanup_expired_tokens {
    schedule = "0 */6 * * *"
    timeout = "5m"
    retry {
      max_attempts = 3
      backoff = "exponential"
    }
  }
  send_daily_digest {
    schedule = "0 8 * * *"
    queue = "low_priority"
  }
}

notifications

Multi-channel notification configuration (email, SMS, WhatsApp, push).
Notification setup
notifications {
  providers {
    email { adapter = "smtp" }
    sms   { adapter = "twilio" }
    push  { adapter = "firebase" }
  }
  order_confirmed {
    channels = [email, push]
    recipient = $instance.customer.email
    template = "order_confirmed"
    locale = $context.locale
  }
}

file_storage

File upload configuration with size limits, type restrictions, and CDN.
File storage
file_storage {
  provider = "s3"
  bucket = "my-app-uploads"
  max_size = "10MB"
  allowed_types = ["image/png", "image/jpeg", "application/pdf"]
  virus_scan = true
  cdn_enabled = true
}

infrastructure

Docker, Redis, Celery, API gateway, CORS, and deployment configuration.
Infrastructure config
infrastructure {
  docker {
    compose_version = "3.8"
    base_image = "python:3.12-slim"
  }
  redis {
    broker = true
    cache = true
    pool_size = 10
  }
  celery {
    concurrency = 4
    queue = "default"
  }
  cors {
    allow = ["https://app.example.com"]
  }
}

platform

Multi-service platform orchestration. Defines service dependencies, shared kernels, and generation order.
Platform definition
platform MyPlatform {
  modules = [UserService, OrderService, NotificationService]
  shared_kernel = [BaseEntity, AuditMixin]
  generation_order = [UserService, OrderService, NotificationService]

  interactions {
    OrderService -> NotificationService {
      pattern = "fire_and_forget"
      event = "order_confirmed"
    }
  }
}

events

Domain event definitions for event-driven communication between services.

tenant_config

Multi-tenancy configuration: isolation strategy, tenant resolution, and feature flags per tier.

task_queue

Async task queue with retry policies, dead-letter queues, and priority levels.

row_level_isolation

Row-level security policies for data isolation.

sequences

Ordered sequence generators (e.g., invoice numbers).

external_adapters

Third-party service integration definitions (Stripe, SendGrid, etc.).

service_observability

Metrics, distributed tracing, structured logging, and health endpoints.

object_storage

S3-compatible object storage configuration.

permissions

Role-based and attribute-based access control definitions.

sagas

Distributed transaction orchestration with compensating actions.

Flow Actions

Actions available in flow steps. Each action maps to a specific operation on the target entity or system.

NameDescriptionSyntax
createCreate a new entity instanceaction = create
updateUpdate an existing entityaction = update
deleteDelete an entity instanceaction = delete
queryQuery entities with filtersaction = query
validateRun validation rulesaction = validate
extractExtract fields from dataaction = extract
calculateCompute derived valuesaction = calculate
state_changeTrigger a state machine transitionaction = state_change
external_callCall an external serviceaction = external_call
batchBatch multiple operationsaction = batch
exportExport data to a formataction = export

Trigger Functions

Functions used in @triggers annotations and event routing.

NameDescriptionSyntax
event()Emit a domain event@triggers(event("user_created"))
job()Enqueue a background job@triggers(job("send_welcome_email"))
state_change()Trigger a state machine transition@triggers(state_change("activate"))

Complete Examples

Full spec examples from simple to complex.

A minimal spec: one entity, REST API, basic security.

Day 1 — Simple User Service
service UserService {
  version = "1.0.0"
  port = 8000
  api_prefix = "/api/v1"
  database = "postgresql"

  entity User @audit @soft_delete {
    id       UUID     @pk @default($computed.uuid)
    email    String   @unique @not_null
    name     String   @not_null
    role     Enum(ADMIN, MEMBER) @default(MEMBER)
    is_active Boolean @default(true)
  }

  api REST @entity(User) @paginated {
    POST   "/users"       @status(201)
    GET    "/users"
    GET    "/users/{id}"
    PUT    "/users/{id}"
    DELETE "/users/{id}"  @roles(ADMIN)
  }

  security {
    auth_scheme = "jwt"
    jwt_algorithm = "HS256"
    token_expiry_minutes = 60
    password_hashing = "bcrypt"
    roles = [ADMIN, MEMBER]
  }
}

A more complex spec with flows, state machines, jobs, and notifications.

Day 5 — E-commerce with Flows and State Machines
service OrderService {
  version = "2.0.0"
  port = 8001
  api_prefix = "/api/v1"
  database = "postgresql"

  entity Order @audit @soft_delete @aggregate_root {
    id          UUID     @pk @default($computed.uuid)
    customer_id UUID     @fk(Customer.id) @not_null @indexed
    total       Decimal  @not_null @check("total >= 0")
    currency    String   @default("USD")
    status      Enum(DRAFT, PENDING, PAID, SHIPPED, DELIVERED, CANCELLED) @default(DRAFT)
    notes       Text     @nullable
  }

  entity OrderItem @audit {
    id         UUID    @pk @default($computed.uuid)
    order_id   UUID    @fk(Order.id) @not_null
    product_id UUID    @not_null
    quantity   Integer @not_null @check("quantity > 0")
    unit_price Decimal @not_null
  }

  state_machine OrderStatus {
    initial = DRAFT

    DRAFT -> PENDING       @roles(MEMBER, ADMIN)
    PENDING -> PAID        @guard("payment_confirmed == true")
    PAID -> SHIPPED        @roles(ADMIN)
    SHIPPED -> DELIVERED
    PENDING -> CANCELLED   @roles(MEMBER, ADMIN)
    DRAFT -> CANCELLED
  }

  flow PlaceOrder {
    step validate {
      action = validate
      target = Order
    }
    step create_order {
      action = create
      target = Order
      mapping {
        id = $computed.uuid
        customer_id = $context.user_id
        status = DRAFT
        total = $input.total
        created_at = $computed.now
      }
    }
    step submit {
      action = state_change
      target = Order
      condition = "$result.id != null"
      mapping {
        status = PENDING
      }
    }
  }

  api REST @entity(Order) @paginated {
    POST   "/orders"          @status(201) @triggers(order_created)
    GET    "/orders"
    GET    "/orders/{id}"
    POST   "/orders/{id}/pay" @triggers(order_paid)
  }

  jobs {
    cancel_stale_orders {
      schedule = "0 * * * *"
      timeout = "2m"
      retry { max_attempts = 3, backoff = "exponential" }
    }
  }

  notifications {
    providers {
      email { adapter = "smtp" }
    }
    order_confirmed {
      channels = [email]
      recipient = $instance.customer.email
      template = "order_confirmed"
    }
  }

  errors {
    ORDER_NOT_FOUND   { status = 404, category = "not_found", message = "Order not found" }
    INSUFFICIENT_STOCK { status = 409, category = "conflict", message = "Insufficient stock" }
  }

  security {
    auth_scheme = "jwt"
    jwt_algorithm = "HS256"
    token_expiry_minutes = 60
    roles = [ADMIN, MEMBER]
    rate_limit { policy = "sliding_window", allow = 100, for = "1m" }
  }

  infrastructure {
    docker { compose_version = "3.8", base_image = "python:3.12-slim" }
    redis { broker = true, cache = true }
    celery { concurrency = 4 }
  }
}