Executable DDD for Spring Boot.
Domain building blocks out of the box, architecture rules enforced in CI, and the same guardrails for humans and AI coding agents.
English · 简体中文 · Documentation · Roadmap
Generate a project, let the domain model reach into the persistence layer, and the build fails with the rule, the class and how to fix it. The output is from a real run.
- 🧱 Domain building blocks:
Identifier,ValueObject,Entity,AggregateRoot, domain events and specifications, with zero framework dependencies enforced by tests - 🛡️ Architecture rules that fail the build: ArchUnit rules for three- and four-layer projects, included in every generated project
- 🗄️ Safe persistence: a generic MyBatis-Plus repository with optimistic locking; missing or duplicate mappers fail at startup
- ⚡ Two-level cache: Caffeine + Redis with cross-instance invalidation, Redis failure fallback and a deserialization allow-list
- 🤖 AI-agent ready: generated projects ship
AGENTS.md,CLAUDE.mdand Claude Code Skills; architecture failures come with a report agents can act on; use cases can be exposed as MCP tools - 🧩 Thirteen Spring Boot starters under one
ddk.*namespace: web, MyBatis, Redis, cache, data sources, tracing, Seata, domain events, MCP, concurrency control, scheduled jobs, read-model projections, ArchGuard - 🚀 Start in minutes: Maven archetypes and a runnable example, built and tested in CI on Java 21 and 25
domain-driven-kit is not a heavy business framework. It is an evolving Java DDD engineering toolkit that turns layered architecture, response contracts, exception handling, pagination, object mapping, repository abstractions, Spring Boot starters and architecture rules into reusable code.
It is designed for teams that want to:
- Start a Java project with a clear DDD / layered architecture baseline
- Keep Controller, Application, Domain and Infrastructure responsibilities explicit
- Standardize repeated backend concerns such as API responses, exceptions, pagination and repository boundaries
- Move architecture rules into tests and CI with ArchUnit instead of leaving them only in documentation
These projects overlap with DDK in places and solve different problems. They are not mutually exclusive, and DDK builds on one of them.
| Project | What it gives you | Reach for it when |
|---|---|---|
| COLA | A layered application architecture with archetypes, plus components such as an extension mechanism and a state machine | You want Alibaba's COLA layering and its components |
| Spring Modulith | Verification of boundaries between business modules, module-level integration tests, and an event publication registry | Your main concern is keeping the modules of a modular monolith apart |
| jMolecules | Annotations and interfaces that name DDD and architecture concepts in code, with integrations that derive rules and boilerplate from them | You want to express the concepts and keep full freedom over implementation |
| DDK | Base classes for the building blocks, a MyBatis-Plus repository, starters for common middleware, archetypes, architecture rules with fix hints, and conventions for AI coding agents | You want a working DDD project on Spring Boot 4 and MyBatis-Plus quickly, with the rules enforced from day one |
DDK does not replace Spring Modulith: reliable domain events in DDK run on Modulith's event publication registry, and module boundaries inside a DDK project can still be verified with it. DDK's layer rules and Modulith's module rules check different axes of the same codebase.
Generate a four-layer service in one command. The script builds DDK, installs it into your local Maven repository and runs the archetype:
curl -fsSL https://raw.githubusercontent.com/poppycoderr/domain-driven-kit/main/scripts/ddk.sh | bash -s -- new order-service --group com.acme
cd order-service && mvn verifyUse --layers 3 for the three-layer skeleton, or DDK_REF=v0.8.0 to build a released version. Run ddk.sh help for all options.
To build DDK by hand instead:
Requirements:
- JDK 21
- Maven 3.9+
- Spring Boot 4.1.x (Jackson 3)
Build locally:
git clone https://github.com/poppycoderr/domain-driven-kit.git
cd domain-driven-kit
mvn -B -ntp verify
mvn -B installUse in another project. Import the BOM first, then drop the versions:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.ddk</groupId>
<artifactId>ddk-dependencies</artifactId>
<version>0.9.0-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.ddk</groupId>
<artifactId>ddk-web-starter</artifactId>
</dependency>
<dependency>
<groupId>com.ddk</groupId>
<artifactId>ddk-mybatis-starter</artifactId>
</dependency>
<!-- Architecture rules belong on the test classpath only -->
<dependency>
<groupId>com.ddk</groupId>
<artifactId>ddk-archguard-starter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>See the full guide: Quick Start.
DDK is maintained by one person and is in its 0.x series: a minor release may contain breaking changes, each listed in the changelog. Releases are published on GitHub rather than Maven Central for now.
| Module | Capability | Status |
|---|---|---|
ddk-core |
Domain model primitives, ApiResponse, exceptions, pagination, mapper registry, repository contract |
Usable |
ddk-test |
Assertions on aggregates and business rules, Testcontainers presets for Redis, MySQL and RocketMQ | Usable, used by DDK's own tests |
ddk-mybatis |
MyBatis-Plus repository implementation, query parsing, pagination, optimistic locking, domain event publishing | Usable, with H2 integration tests |
ddk-web-starter |
Jackson, CORS, global exception handling, and the error contract in OpenAPI docs when springdoc is present, configurable under ddk.web.* |
Usable |
ddk-mybatis-starter |
Pagination, optimistic locking, full-table update/delete guard, snowflake IDs, audit fields and multi-tenancy from the operator context, configurable under ddk.mybatis.* |
Usable, with H2 integration tests |
ddk-event-starter |
Spring-backed domain event publisher | Usable |
ddk-mcp-starter |
Application use cases as MCP tools: argument validation, error codes, audit log, streamable HTTP by default | Usable, with MCP client end-to-end tests |
ddk-concurrency-starter |
@AggregateLock, @Idempotent and @RateLimit on Redisson: one operation per aggregate, one execution per request, a call budget per user or tenant |
Usable, with Redis integration tests |
ddk-job-starter |
@Scheduled jobs that run on one instance at a time, on ShedLock with the lock in Redis |
Usable, with Redis integration tests |
ddk-projection-starter |
Read models refreshed from the write model: marked in the transaction, refreshed after commit, retried, rebuildable | Usable, tested on H2, MySQL and PostgreSQL |
ddk-redis-starter |
JSON RedisTemplate with a deserialization type allow-list |
Usable |
ddk-cache-starter |
Caffeine (L1) + Redis (L2) two-level cache with cross-instance invalidation and Redis failure fallback | Usable, with Redis integration tests |
ddk-archguard-starter |
ArchUnit rules for layering and domain purity | Usable |
ddk-dependencies |
BOM, so downstream projects stop writing versions | Usable |
ddk-db-starter |
Named data sources with configurable pools and a validated primary | Usable |
ddk-tracer-starter |
Distributed tracing with the trace ID in a response header | Usable |
ddk-seata-starter |
Distributed transactions with XID propagation on outbound HTTP calls | Usable |
ddk-archetypes |
Three- and four-layer Maven archetypes with architecture tests in every generated project | Usable, with integration tests on generated projects |
ddk-examples |
ddk-example-user: a runnable four-layer user registration example. ddk-mall: a reference application where order, inventory and payment contexts work together through integration events, using every starter side by side |
Usable |
com.ddk.core.domain does exactly three things:
- Gives identity a type.
IdentifiermakesUserId(1)different fromOrderId(1), so swapped arguments fail at compile time - Separates value equality from identity equality.
ValueObject(an empty interface, so arecordcan implement it) andEntity - Gives domain events a place to be collected and published.
AggregateRootregisters them,DomainEventPublisherpublishes them after commit
The package depends on no framework at all — not Spring, MyBatis or Jackson. That constraint is enforced by DomainPackagePurityTest, not by a note in the docs.
The primitives provide mechanism without dictating process, and you can adopt only the part you need.
Core constraints:
adapteradapts external protocols and should not contain business rulesapplicationorchestrates use cases, transactions and domain objectsdomainowns business rules and should not depend on Spring, MyBatis, Jackson or other frameworksinfrastructureimplements repository and external dependency contracts defined by the domain layer
Written in a document these are suggestions; written as a test they are constraints:
class ArchitectureTest {
private final JavaClasses classes = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_JARS)
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.example.myapp");
@Test
void layered_architecture_is_respected() {
CommonArchRules.LAYERED_ARCHITECTURE_RULE.check(classes);
}
@Test
void domain_stays_framework_free() {
CommonArchRules.DOMAIN_MUST_NOT_DEPEND_ON_FRAMEWORKS.check(classes);
}
}A violation fails the build. See ddk-examples/ddk-example-user for a working example.
domain-driven-kit
├── ddk-dependencies BOM, so downstream projects stop writing versions
├── ddk-core Core abstractions: domain model, exception, response, pagination, mapper, repository contract
├── ddk-test Domain assertions and Testcontainers presets
├── ddk-mybatis MyBatis-Plus repository implementation and query adapters
├── ddk-starters Spring Boot starter modules
│ ├── ddk-web-starter
│ ├── ddk-mybatis-starter
│ ├── ddk-redis-starter
│ ├── ddk-cache-starter
│ ├── ddk-db-starter
│ ├── ddk-tracer-starter
│ ├── ddk-seata-starter
│ ├── ddk-event-starter
│ ├── ddk-mcp-starter
│ ├── ddk-concurrency-starter
│ ├── ddk-job-starter
│ ├── ddk-projection-starter
│ └── ddk-archguard-starter
├── ddk-archetypes 3-layer / 4-layer project skeletons
└── ddk-examples Example applications
Inside ddk-core:
com.ddk.core
├── domain Domain model primitives, zero framework dependencies
├── repository The GenericRepository contract
├── page PageQuery / PageResponse / Sort
├── mapper MapperProvider and @EnhancedMapper
├── response ApiResponse
└── exception ErrorCode and the exception hierarchy
Released so far:
-
v0.1 Modern baseline: Spring Boot 4.1 / Jackson 3 and the first GitHub Release
-
v0.2 AI collaboration: generated projects ship
AGENTS.mdand Skills, ArchGuard reports violations agents can act on, an MCP starter on Spring AI -
v0.3 Reliable domain events: transactional outbox, Kafka / RocketMQ delivery, event contracts, idempotent consumers
-
v0.4 Middleware integrations: aggregate locks, duplicate-submit protection and rate limits, scheduled jobs, Flyway, the error contract in API docs,
ddk-test -
v0.5 Operator context: audit fields and fail-closed multi-tenancy driven by one operator context, ArchGuard fix hints in English
-
v0.6 Events end to end: declared consumers, traces that follow events across contexts, and the
ddk-mallreference application -
v0.7 Fail where the mistake is made: events published outside a transaction and locks taken inside one are rejected on the spot; job locks without Redis
-
v0.8 The query side: read models refreshed from the write model and rebuildable, row-level data scope
Next:
- More integrations: Elasticsearch as a read-model store, Nacos, Sentinel, object storage
- v1.0 Production ready: native images, a frozen public API
See ROADMAP.md for the full plan.
- DDK documentation
- Quick Start
- Domain Model Primitives
- Layering and Architecture Guard
- Development and Refactoring Plan
Issues and PRs are welcome. The most useful contributions right now are:
- Starter auto-configuration fixes
- Tests and runnable examples
- DDD layering examples and documentation
- Clearer trade-off analysis for existing design decisions
Run mvn verify before opening a PR: it checks formatting with Spotless (fix with mvn spotless:apply) and requires at least 70% line and 50% branch coverage per module. Main code is @NullMarked: mark anything that may be null with @Nullable, or NullAway fails the compile.
- Code and docs are written in IntelliJ IDEA with the help of Claude Code and Codex; every change is reviewed, tested and passes CI before it is merged.
- The documentation site codesphere is built with VitePress; earlier versions used docsify.
Apache License 2.0. Free to use, modify and distribute, including commercially; keep the copyright and license notices, and state changes made to modified files.