Skip to content

DDK Architecture

Platform Users — Engineers & Low-code Ops Users (ORA / Panel Builder) OR Platform ORA — AI Planning Interface Agent Workflows Plan Visualisation ADK Integration SDK UI — Frontend Shell FDK Architecture Low code Config-driven DDK Schema Definition Code Generator Generated Server MDK WEM DAL Experiment Manager Nexus Deployment Control Live Monitoring Registry Browser SCDK Source Control Pipeline Mgmt Azure DevOps deploys ↓ SDK API — GraphQL Federation Gateway Federation Gateway Component Resolvers Auth & Licensing Plugins: gql-autogeneration Migrator Helm KinD Boilerplate GenAI ··· Microservices — Domain IP Services Data Pipeline Core Platform Metrics & Analytics Spatial & Geo Simulation Event Detection Camera & Device Fire & Resource Opt. Satellite Modelling ↓ Nexus deploys Deployed OR Applications Rail Ops Dashboard Mine Mgmt Dashboard Port Ops Dashboard ··· FDK-built · DDK-backed · MDK-powered · deployed via Nexus ↑ Application Users — Operations Teams (shift managers, analysts, planners)

Overview

The Data Development Kit (DDK) is a code generation system that creates production-ready GraphQL API servers from declarative schemas. It follows a schema-first approach where you define your data model using GraphQL schema files, and the DDK generates complete server applications with database integration, API endpoints, and business logic scaffolding.

Core Concepts

Schema-First Design

The DDK starts with your data model defined in GraphQL schema language:

  1. Define Your Schema — Describe entities, fields, and relationships in GraphQL format
  2. Add Directives — Use special annotations to configure database mapping and validation
  3. Generate Server — DDK creates complete application code from the schema
  4. Customize Logic — Add your business-specific code to generated stubs

This approach ensures your API always matches your data model, reducing drift between documentation and implementation.

Code Generation

The DDK generates all the repetitive parts of a GraphQL server:

  • Data Models — Type-safe structures matching your schema
  • Database Layer — ORM models with relationships and migrations
  • CRUD Resolvers — Standard create, read, update, delete operations
  • API Documentation — OpenAPI/Swagger specs generated automatically
  • Resolver Stubs — Placeholders for your custom business logic

What Gets Generated:

  • ✅ Database models and migrations
  • ✅ GraphQL resolvers for all basic operations
  • ✅ Type definitions and validation
  • ✅ API documentation
  • ✅ Boilerplate server setup

What You Provide:

  • Your GraphQL schema with entity definitions
  • Custom business logic in designated files
  • Configuration for database and services

Generated vs Custom Code

The DDK separates generated code from custom code:

Generated Files:

  • Automatically created and updated when schema changes
  • Never edit these directly — changes will be overwritten
  • Handle all standard CRUD operations

Custom Files:

  • Where you write your business logic
  • Preserved during regeneration
  • Implement specialized queries, mutations, and business rules

This separation means you can update your schema and regenerate without losing your custom code.

Architecture Layers

A DDK-generated server has several layers:

1. API Layer (GraphQL)

The entry point for client applications:

  • GraphQL Endpoint — Handles queries and mutations
  • Type System — Enforces schema contracts
  • Resolvers — Connect GraphQL fields to data sources
  • Validation — Ensures requests match schema

2. Business Logic Layer

Your custom code and generated CRUD operations:

  • Custom Resolvers — Your specialized business logic
  • Generated CRUD — Standard create, read, update, delete
  • Computed Fields — Derived values and transformations
  • Access Control — Authorization rules

3. Data Access Layer

Database interaction through ORM:

  • ORM Models — Type-safe database entities
  • Relationships — Automatic joining and eager loading
  • Transactions — Atomic operations for data consistency
  • Migrations — Database schema version control

4. Database Layer

Persistent storage:

  • PostgreSQL — Relational data storage
  • Redis — Caching and session storage
  • Migrations — Track schema evolution over time

How Generation Works

When you run the DDK generator:

  1. Schema Parsing — Reads your GraphQL schema files
  2. Validation — Checks schema is valid and consistent
  3. Code Generation — Creates application code from templates
  4. Compilation — Builds the generated server
  5. Migration Creation — Generates database migration scripts

The generator creates:

  • Server application with all routes and handlers
  • Database models matching your schema
  • GraphQL resolvers for standard operations
  • Migration files to update database schema
  • API documentation

Schema Directives

DDK extends GraphQL with custom directives for configuration:

@table

Marks a type as a database table:

graphql
type User @table {
  id: ID!
  name: String!
  email: String!
}

@required

Marks fields as non-null in database:

graphql
type Product @table {
  name: String! @required
  price: Float! @required
}

@constraint

Adds database constraints:

graphql
type User @table {
  email: String! @constraint(unique: true)
}

@mapping

Customizes database column names:

graphql
type Article @table {
  createdAt: DateTime! @mapping(name: "created_timestamp")
}

These directives let you control database behavior without writing code.

Workflow

Initial Server Creation

  1. Define Schema — Create GraphQL schema files describing your data
  2. Run Generator — DDK creates complete server application
  3. Review Generated Code — Understand what was created
  4. Start Server — Run the generated application
  5. Test API — Use GraphQL playground to test queries

Adding Custom Logic

  1. Identify Need — Custom query, business rule, or computed field
  2. Locate Custom File — Find the appropriate custom resolver file
  3. Implement Logic — Write your business logic
  4. Test — Verify custom functionality works
  5. Iterate — Refine as needed

Schema Evolution

  1. Update Schema — Add, modify, or remove types and fields
  2. Regenerate — Run DDK generator again
  3. Review Changes — Check what code changed
  4. Migrate Database — Apply new migration files
  5. Update Custom Code — Adjust custom resolvers if needed

Benefits of Schema-First

Consistency

  • API matches schema exactly
  • Database structure matches schema
  • Documentation always accurate
  • No drift between layers

Productivity

  • No boilerplate code to write
  • CRUD operations work immediately
  • Focus on business logic, not infrastructure
  • Rapid prototyping and iteration

Quality

  • Type-safe throughout stack
  • Validation built-in
  • Consistent patterns across all endpoints
  • Easier to maintain and understand

Flexibility

  • Custom logic where you need it
  • Generated code where you don't
  • Easy to evolve schema over time
  • Multiple servers from one approach

Integration with MDK

The MDK's own backend (Experiment Manager) is a DDK-generated server. This demonstrates the DDK's production-readiness and validates that it can handle complex, real-world applications.

When MDK workflows use IMPORT_DDK and EXPORT_DDK task types, they're connecting to DDK-generated GraphQL servers to read and write structured domain data.

Best Practices

Schema Design

  1. Start Simple — Begin with core entities, add complexity gradually
  2. Name Clearly — Use descriptive names for types and fields
  3. Group Related — Keep related types in same schema file
  4. Document Intent — Add comments explaining business meaning

Custom Code

  1. Isolate Logic — Keep business rules in custom resolver files
  2. Validate Inputs — Check data before processing
  3. Handle Errors — Return meaningful error messages
  4. Test Thoroughly — Write tests for custom logic

Migrations

  1. Review Before Apply — Check migration SQL makes sense
  2. Test on Copy — Try migrations on dev database first
  3. Backup Production — Always backup before migrating
  4. Roll Forward — Prefer new migrations over editing old ones

Common Patterns

One-to-Many Relationships

graphql
type Author @table {
  id: ID!
  name: String!
  books: [Book!]!
}

type Book @table {
  id: ID!
  title: String!
  authorId: ID!
  author: Author!
}

Many-to-Many Relationships

Use junction tables for many-to-many:

graphql
type Student @table {
  id: ID!
  name: String!
  enrollments: [Enrollment!]!
}

type Course @table {
  id: ID!
  name: String!
  enrollments: [Enrollment!]!
}

type Enrollment @table {
  studentId: ID!
  courseId: ID!
  student: Student!
  course: Course!
}

Computed Fields

Add custom resolvers for derived values:

graphql
type Order @table {
  id: ID!
  subtotal: Float!
  taxRate: Float!
  total: Float!  # Computed in custom resolver
}

See Also

User documentation for Optimal Reality