Skip to content

Use cases

One spec.Four kinds of work.

One DOGM spec describes a fictional dataset: its tables, how they join and the rules every row must pass. The same YAML file can seed a dev database, force the rare paths in QA, pin down an AI evaluation set or fill a demo account.

One spec, four kinds of workA spec stands at the centre of the platform with four branches running out of it: to a development database, a table of edge-case values for QA, a stack of labelled evaluation cards, and a laptop running a demo.0NULLspec

Where things stand: The in-browser demo runs today with shop, hiring and support scenarios. Hosted runs compile and run specs like these in the early-access beta, and the dogm CLI runs them on your machine; until its first release, you build it from source.

01 Use case

Application development

Who it is for
Developers building features against a local or shared development database.
The problem
Empty tables hide bugs, and a copy of production puts real customers on every laptop. Hand-written fixtures drift from the schema, and half their foreign keys point at nothing.
How DOGM helps
  • Every order belongs to a customer and every key resolves, by construction.
  • Names, mobile numbers and cities follow Philippine formats, so screens look the way they will in production.
  • Row counts are a run input, so one spec seeds a 50-row laptop database and a 10-million-row staging one.
shop.dogm.yamlspec excerpt
spec_version: 1
locale: en-PH
tables:
  customers:
    rows: 200
    primary_key: { column: customer_id, format: "CUS-{n:06}" }
    columns:
      full_name: { gen: person.full_name, pii: person.name }
      email:     { gen: person.email, from: full_name, unique: true, pii: person.email }
      mobile:    { gen: ph.mobile }
      city:      { gen: ph.city, weights: population }
  orders:
    rows_per_parent: { parent: customers, dist: uniform, min: 1, max: 3 }
    primary_key: { column: order_id, format: "ORD-{n:07}" }
    columns:
      customer_id: { ref: customers.customer_id }
      total_php:   { gen: money, currency: PHP, between: [249, 12500] }

02 Use case

QA and edge cases

Who it is for
QA engineers and testers who need the rare paths to show up on purpose.
The problem
Cancelled orders, refunds and empty optional fields are rare in real data, so a test run hits them by luck or not at all.
How DOGM helps
  • Weights turn up the rare states. Here, half of all orders are cancelled.
  • A payment's status follows its order, so a cancelled order always has a refunded payment.
  • Rules run on every row and land in the report, so a broken total shows up as a finding before it shows up in a bug ticket.
refunds.dogm.yamlspec excerpt
spec_version: 1
locale: en-PH
tables:
  orders:
    rows: 500
    primary_key: { column: order_id, format: "ORD-{n:07}" }
    columns:
      item_count:     { gen: int, between: [1, 5] }
      unit_price_php: { gen: choice, values: [249, 399, 589, 1250, 2499], type: money }
      total_php:      { expr: "item_count * unit_price_php" }
      status:         { gen: choice, values: [processing, shipped, delivered, cancelled], weights: [1, 1, 1, 3] }
      gift_note:      { gen: text.sentence, nullable: 0.4 }
  payments:
    rows_per_parent: { parent: orders, exactly: 1 }
    primary_key: { column: payment_id, format: "PAY-{n:07}" }
    columns:
      order_id:   { ref: orders.order_id }
      amount_php: { expr: "parent.total_php" }
      status:     { map: parent.status, cases: { cancelled: refunded, processing: pending }, default: paid }
rules:
  - "payments.amount_php == parent.total_php"

03 Use case

AI evaluation

Who it is for
Teams testing models, prompts or agents on conversations and records.
The problem
An evaluation only means something if you can rerun it on the same inputs, and real support logs are full of personal data.
How DOGM helps
  • The seed is a run input, not part of the spec: the same spec and seed give the same rows, in the same order.
  • Reply threads alternate between customer and agent, and each reply's timestamp comes after the one before it.
  • Message text comes from fixed lists, so nothing in the set describes a real person.
support.dogm.yamlspec excerpt
spec_version: 1
locale: en-PH
tables:
  tickets:
    rows: 300
    primary_key: { column: ticket_id, format: "TCK-{n:06}" }
    columns:
      opened_at:   { gen: datetime, between: [2026-01-05T00:00, 2026-03-26T00:00] }
      category:    { gen: choice, values: [billing, delivery, account, bug], weights: [3, 2, 1, 1] }
      reply_count: { gen: int, between: [1, 4] }
  replies:
    rows_per_parent: { parent: tickets, count: "parent.reply_count" }
    primary_key: { column: reply_id, format: "RPL-{n:07}" }
    columns:
      ticket_id:   { ref: tickets.ticket_id }
      author_role: { expr: "if(ordinal % 2 == 0, 'customer', 'agent')" }
      sent_at:     { gen: datetime, after: "coalesce(prev.sent_at, parent.opened_at)", within_minutes: [5, 600] }
      body:
        gen: choice
        by: author_role
        cases:
          customer: ["It happens every morning, around 9:00.", "Still not working after a restart."]
          agent: ["Thanks for reaching out. We're looking into this now.", "This is fixed on our side. Can you try again?"]
rules:
  - "replies.sent_at > parent.opened_at"

04 Use case

Demos and sales environments

Who it is for
Sales engineers, founders and product teams showing software to prospects.
The problem
A demo account full of lorem ipsum looks unfinished, and a demo built from a customer's data is a privacy incident waiting for a screen share.
How DOGM helps
  • Companies, job titles and peso salaries that read like a Philippine business.
  • Government ID columns such as TIN are format-valid and labelled synthetic in the report. They are not guaranteed to differ from real numbers.
  • Emails use reserved example domains, so a demo can never mail a real inbox.
payroll-demo.dogm.yamlspec excerpt
spec_version: 1
locale: en-PH
tables:
  companies:
    rows: 12
    primary_key: { column: company_id, format: "CMP-{n:04}" }
    columns:
      name:   { gen: company.name }
      region: { gen: ph.region }
  employees:
    rows_per_parent: { parent: companies, dist: uniform, min: 5, max: 40 }
    primary_key: { column: employee_id, format: "EMP-{n:06}" }
    columns:
      company_id: { ref: companies.company_id }
      full_name:  { gen: person.full_name, pii: person.name }
      email:      { gen: person.email, from: full_name, pii: person.email }
      job_title:  { gen: job.title }
      tin:        { gen: ph.tin, pii: ph.tin }
      salary_php: { gen: money, currency: PHP, dist: lognormal, median: 32000 }

See it working

Try a scenarioin your browser.

The demo generates connected records, masks names and emails, runs the checks and exports CSV without leaving the page.