Domain Driven Design

GDL (Go-Duck Language)

The standard DSL for generating your massive suite of code from a simple text file.

GDL Syntax & Structure

GDL allows you to define your core business entities and the relationships between them. It looks and acts slightly similarly to JHipster's JDL.

schema.gdl
@Audited 
entity Article {
  title String required unique
  content Text required
  status ArticleStatus required
  publishedDate LocalDate
  views Integer
  metadata JSONB
}

enum ArticleStatus {
  DRAFT, PUBLISHED, ARCHIVED
}

entity Author {
  name String required
  biography Text
  settings JSON
}

relationship OneToMany {
  Author{article} to Article{author} required
}

Supported Data Types

GDL Type Go Struct Type Postgres / SQL Type GraphQL / Proto
StringstringVARCHAR(255)String / string
String(N)stringVARCHAR(N)String / string
TextstringTEXTString / string
JSONdatatypes.JSONJSONString / string
JSONBdatatypes.JSONJSONBString / string
IntegerintINTInt / int32
Longint64BIGINTID / int64
Floatfloat64DECIMALFloat / float32
BigDecimalfloat64DECIMALFloat / double
BooleanboolBOOLEANBoolean / bool
LocalDatetime.TimeDATEString / string
Instanttime.TimeTIMESTAMPString / string
EnumCustomTypeVARCHAR(50)String / string

Enumerations

GDL supports custom Enum types for fields that have a predefined set of allowed values. Enums are generated as Go types with constants and mapped to safe string columns in the database.

enum Language {
  ENGLISH, FRENCH, GERMAN
}

entity Person {
  name String required
  nativeLanguage Language
}

Modifiers & Annotations

required

Forces the field to be NOT NULL in the database, missing fields are blocked by the Gin validator natively.

unique

Adds a standard UNIQUE constraint indexing configuration at the database level.

@Audited

An entity annotation that completely re-wires the structural behavior of the model. Standard created_at triggers are bypassed and 5 highly-detailed audit columns are injected: created_by, created_date, last_modified_by, last_modified_date, last_modified_user_id. All changes are captured implicitly by the JWT middleware.

Incremental Migration Engine

Running go-duck import-gdl app.gdl compares your GDL file against the physical .go-duck/ snapshot state securely stored in the repo.

It detects exactly what changed (such as removing a field, changing field types, adding new nested JSON) and generates precise atomic standard Liquibase XML migrations/liquibase/changelogs/ scripts to evolve the live database safely without destroying data.

Golden Rule

Avoid editing Liquibase XML manually unless correcting an anomaly. Let the GDL manage your migrations.

Managing Relationships

Relationships in GDL define how entities connect at the database level (foreign keys) and how they are represented in Go structs and GraphQL schemas. Just like JHipster, we support four primary types.

One-to-Many Most Common

Example: An Author has many Articles.

relationship OneToMany {
  Author{article} to Article{author}
}

This generates a author_id foreign key in the article table and a slice of Articles in the Author struct.

Many-to-One

Essentially the inverse of One-to-Many, used to specify the owner side explicitly.

relationship ManyToOne {
  Article{author} to Author
}

One-to-One

Example: A User has exactly one Profile.

relationship OneToOne {
  User{profile} to Profile{user}
}

Many-to-Many

Example: Students enrolled in many Courses.

relationship ManyToMany {
  Student{course} to Course{student}
}

This triggers the automatic generation of a join table (e.g., student_course) in Liquibase.