Skip to content

FAQs

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)

Frequently asked questions about the Data Development Kit (DDK).

Table of Contents


General Questions

What is the DDK?

The DDK (Data Development Kit) is a code generation service that creates complete GraphQL servers in Go from schema definitions. It generates a fully functional API with database integration, Docker configuration, and complete server infrastructure.

How does the DDK differ from gqlgen?

  • gqlgen: Low-level code generation library, requires manual configuration
  • DDK: High-level service that uses gqlgen internally and adds automatic CRUD operations, database integration with GORM and PostgreSQL, custom directive system, complete server scaffolding, Docker setup, and relationship management.

When should I use the DDK?

Use the DDK when you need rapid GraphQL API development with automatic CRUD operations, PostgreSQL integration, relationship management between entities, built-in authentication, and consistent code structure across your services.

The DDK is the right choice for teams building data services that will evolve over time — where the schema will change, new types will be added, and the ability to regenerate without losing custom code is essential. If you need a GraphQL API that you write once and never regenerate, you could use the DDK for initial scaffolding and then treat the output as a starting point. But the DDK's real value is in the ongoing development cycle: edit schema, regenerate, continue. Teams that want instant, zero-code database APIs backed by an existing database should look at Hasura or PostGraphile. Teams that need a generated starting point they can build sophisticated domain logic on top of — while retaining full control of the generated code — should use the DDK.

What is generated vs what is manual?

Generated (automatic):

  • GraphQL schema files
  • CRUD resolvers for all operations
  • Database models and repositories
  • GraphQL type definitions
  • Server configuration
  • Docker setup

Manual (your code):

  • Custom resolver implementations
  • Business logic
  • Custom validation
  • External integrations

Schema Design

Do I have to use all CRUD operations?

No! Use the @required directive to specify which operations you need. You can choose any combination of CREATE, READ, UPDATE, and DELETE operations for each type.

Can I use custom scalars?

Yes! The DDK supports custom scalars including Time (for timestamps), JSON (for flexible data structures), and Upload (for file uploads).

How do I model optional vs required fields?

Use GraphQL's type system with the exclamation mark (!) to denote required fields. Fields without the exclamation mark are optional. In the database, required fields become NOT NULL columns while optional fields become nullable columns.

Can I have multiple many-to-many relationships between the same types?

Not directly. Use intermediate types to model each relationship separately. This provides better clarity and control over the relationship data.

How do I create a unique composite constraint?

Use a join table with composite primary key by applying the @constraint(type: "primarykey") directive to multiple fields. Both fields together form the primary key, ensuring uniqueness.

Can I use check constraints with multiple columns?

Yes, check constraints can reference multiple columns. Note that SQL column names use snake_case, so GraphQL field names in camelCase are converted appropriately in constraints.


Generated Code

Can I modify generated code?

DO NOT modify:

  • Generated resolver files - Regenerated every time
  • Generated schema files - Recreated from your schema definitions
  • Generated configuration files - Regenerated with each build

SAFE to modify:

  • Custom resolver files (marked with custom naming convention)
  • Server entry point (after initial generation)
  • Custom service implementations
  • Environment configuration

What happens to my custom resolvers when I regenerate?

They are preserved! The DDK uses file naming conventions to distinguish between generated and custom code. Custom resolver files are never overwritten during regeneration, allowing you to safely update your schema and regenerate without losing business logic.

How do I add custom middleware?

Edit the middleware directory after generation and register your custom middleware in the server entry point.

Can I change the GraphQL endpoint?

Yes, edit the server entry point to modify the GraphQL endpoint path.

How do I add custom types that aren't in the schema?

Create custom type definitions in the models directory and use them in your custom resolvers.


Custom Resolvers

Do custom resolvers require database transactions?

Not required, but highly recommended for consistency across operations, rollback on errors, and proper connection pooling.

Can I call other generated resolvers from custom resolvers?

Yes! Access repository methods to leverage generated CRUD operations within your custom business logic.

How do I return errors from custom resolvers?

Return standard errors directly. The GraphQL layer automatically converts them to GraphQL error responses.

Can I use external APIs in custom resolvers?

Yes, custom resolvers can call external services, APIs, or any other integration you need for your business logic.

How do I implement subscriptions?

Use channels to implement real-time subscriptions. The GraphQL server supports WebSocket-based subscription handling.


Database Operations

Does the DDK support database migrations?

Auto-migration (development):

  • Automatically creates and updates tables during development
  • Does not drop columns or tables

Manual migrations (production):

  • Disable auto-migration in production
  • Use migration tools for better control over schema changes
  • Recommended for production deployments

Can I use composite primary keys?

Yes, apply the primary key constraint to multiple fields to create a composite primary key.

How do I handle soft deletes?

Add a timestamp field for tracking deletions and implement custom delete logic that updates the timestamp instead of removing the record.

Can I use different PostgreSQL schemas?

Yes, configure the database schema name in the server configuration. All tables will be created in the specified schema.

How do I handle connection pooling?

The ORM handles connection pooling automatically. You can configure pool settings such as maximum idle connections, maximum open connections, and connection lifetime.


Performance and Optimization

How do I optimize queries with many relationships?

Use GraphQL field selection to load only the relationships your query needs. The generated resolvers use lazy loading, so unrequested relationships aren't fetched.

Can I add database indexes?

Yes, but requires manual migration. Create database indexes on frequently queried columns to improve query performance.

How do I implement pagination?

Generated list operations have built-in pagination with limit, offset, sorting by field, and sort order parameters. For custom resolvers, implement pagination manually using similar parameters.

Should I use Redis caching?

Use Redis for:

  • Session storage
  • Authentication token management
  • Frequently accessed data
  • Rate limiting
  • Pub/sub for subscriptions

Redis integration is available through server configuration.

How do I batch queries to avoid N+1 problems?

Implement custom resolvers with batching using dataloader libraries to efficiently load related entities in batches rather than one at a time.


Deployment

  1. Application: Docker container
  2. Database: Managed PostgreSQL service
  3. Redis: Managed Redis service
  4. Orchestration: Kubernetes or container orchestration platform
  5. Load Balancer: Standard load balancing solution
  6. Secrets: Secure secrets management service
  7. Monitoring: Logging and monitoring system

How do I deploy to Kubernetes?

Create Kubernetes manifests for deployment configuration, services, secrets, and ingress. The generated server includes Docker configuration that works with standard Kubernetes deployment patterns.

How do I handle database migrations in production?

Option 1: Init container that runs migrations before application starts

Option 2: CI/CD pipeline step that runs migrations during deployment

Option 3: Separate migration job that runs before deploying new versions

How do I configure environment variables?

Use environment files or environment configuration. The server reads configuration from environment variables for database connection, server settings, Redis configuration, authentication secrets, and logging levels.

How do I enable HTTPS?

Option 1: Use a reverse proxy (recommended) with SSL termination

Option 2: Configure the server directly with SSL certificates


Troubleshooting

"Invalid schema" error when validating

Common causes:

  1. Missing primary key on a type
  2. Invalid relationship with foreign key referencing non-existent type
  3. Syntax error in constraint definition
  4. Missing required directive

Solution: Run schema validation and read error messages carefully to identify the specific issue.

"Port already in use" error

Solution 1: Change the server port in configuration

Solution 2: Stop the process using the port

Generated resolvers not working after regeneration

Check:

  1. Did you run regeneration (not initial creation)?
  2. Are schema files in the correct location?
  3. Did the code generation run successfully? (check logs)
  4. Did database schema change? (run migration if needed)

Solution: Delete generated files and regenerate from clean state.

Custom resolvers not called

Check:

  1. Is the custom resolver directive present in the schema?
  2. Is the file named correctly as a custom resolver?
  3. Is the file in the correct directory?
  4. Did you regenerate after adding the custom operation?

Database connection failed

Check:

  1. PostgreSQL is running
  2. Credentials are correct
  3. Database exists
  4. Host and port are correct
  5. Firewall allows connection

Memory leaks in subscriptions

Cause: Not closing channels when client disconnects

Solution: Always check for context cancellation and close channels properly when subscriptions end.

Slow query performance

Solutions:

  1. Add database indexes on frequently queried columns
  2. Use eager loading for relationships to avoid N+1 queries
  3. Implement pagination for large result sets
  4. Use Redis caching for frequently accessed data
  5. Optimize constraints and complex queries

Type assertion errors in custom resolvers

Always check if context values exist before asserting their type to avoid panics from nil values.


Getting Help

Where can I find more examples?

How do I report bugs?

Contact your internal development team or check your organization's issue tracking system.

Where can I learn more about GraphQL?

Where can I learn more about GORM?


User documentation for Optimal Reality