Appearance
DDK Architecture
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:
- Define Your Schema — Describe entities, fields, and relationships in GraphQL format
- Add Directives — Use special annotations to configure database mapping and validation
- Generate Server — DDK creates complete application code from the schema
- 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:
- Schema Parsing — Reads your GraphQL schema files
- Validation — Checks schema is valid and consistent
- Code Generation — Creates application code from templates
- Compilation — Builds the generated server
- 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
- Define Schema — Create GraphQL schema files describing your data
- Run Generator — DDK creates complete server application
- Review Generated Code — Understand what was created
- Start Server — Run the generated application
- Test API — Use GraphQL playground to test queries
Adding Custom Logic
- Identify Need — Custom query, business rule, or computed field
- Locate Custom File — Find the appropriate custom resolver file
- Implement Logic — Write your business logic
- Test — Verify custom functionality works
- Iterate — Refine as needed
Schema Evolution
- Update Schema — Add, modify, or remove types and fields
- Regenerate — Run DDK generator again
- Review Changes — Check what code changed
- Migrate Database — Apply new migration files
- 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
- Start Simple — Begin with core entities, add complexity gradually
- Name Clearly — Use descriptive names for types and fields
- Group Related — Keep related types in same schema file
- Document Intent — Add comments explaining business meaning
Custom Code
- Isolate Logic — Keep business rules in custom resolver files
- Validate Inputs — Check data before processing
- Handle Errors — Return meaningful error messages
- Test Thoroughly — Write tests for custom logic
Migrations
- Review Before Apply — Check migration SQL makes sense
- Test on Copy — Try migrations on dev database first
- Backup Production — Always backup before migrating
- 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
- DDK Overview — High-level introduction to the DDK
- Schema Guide — Detailed schema syntax and patterns
- MDK Architecture — Example of DDK-generated server in production
