Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

386 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mixology Modular Monolith

CI

A working Go modular-monolith example built around a cocktail bar. Seven bounded contexts share one application and embedded database while keeping their commands, queries, persistence, policies, events, and presentation adapters explicit. The same application is exposed as a CLI, Bubble Tea TUI, and Fyne desktop client.

The sample is intentionally stateful rather than a collection of isolated CRUD screens. Orders reserve Inventory, stock changes can block Orders and degrade published Menus, and ingredient retirement either puts dependent Drinks under review or explicitly replaces compatible recipe references. Draft publication consults a queryable readiness report, so the reciprocal event and consistency boundaries remain visible across all three front ends.

Five-minute start

Go 1.26.5 or newer is required. From the repository root:

go run ./main/seed
go run ./main/cli ingredients list
go run ./main/tui
# In another terminal, the desktop client can share the same local database.
go run ./main/gui

All entrypoints use data/mixology.db by default. Override it with --db or MIXOLOGY_DB. CLI, TUI, and GUI processes on the same machine may use that local file concurrently; SQLite serializes writes and waits up to 10 seconds for a busy writer. The GUI and TUI automatically re-query after another connection commits; stale edits are rejected with an optimistic-concurrency conflict rather than overwriting newer data. Database files created by the former bstore backend are incompatible; reseed them or export/import their data with the previous application version before opening this version. They also share actor, logging, and metrics options; run any entrypoint with --help for the full set. The desktop client has additional native prerequisites.

For a useful first code trace, start at one executable, follow its domain surface adapter, then follow the public domain module into a query or command:

main/<surface> -> app/domains/<domain>/surfaces/<surface>
               -> app/domains/<domain>/module.go
               -> queries/ or internal/commands/

Development loop

go generate ./...
go build ./...
go test ./...
go tool arch-lint -config=.arch-lint.yaml

Before opening a PR, run the complete local CI sequence. Application tests should normally begin with testutil.NewFixture(t) so they exercise the real authorization, transaction, event, and audit pipelines against an isolated database.

Documentation map

If you want to… Start here
Understand bounded contexts, pipelines, events, authz, and enforced boundaries Architecture
Use fulfillment, retirement, filters, tags, audit, IDs, or personas Application features
Work on an executable and its composition layer CLI, TUI, or GUI
Reuse or extend presentation mechanics Presentation toolkits
Add a domain-owned presentation adapter Domain surfaces
Change shared domain value types Application kernel
Follow the guided build narrative Tutorial series

Shared infrastructure has focused guides for authorization, the event dispatcher, application errors, typed filters, and the persistence store. The middleware pipeline, telemetry, and test utilities have their own extension and testing guides.

Repository map

app/
  app.go                 application composition root
  domains/<domain>/      bounded contexts and their surface adapters
  kernel/                shared domain value types
pkg/
  middleware/            command/query pipelines and unit of work
  authn/, authz/         actors and Cedar integration
  dispatcher/            generated event-to-handler routing
  filter/, store/        transport-neutral filtering and persistence
  toolkits/              application-independent CLI/TUI/GUI mechanics
  testutil/              production-shaped fixtures and surface drivers
main/
  cli/, tui/, gui/       executable composition and process lifecycle
  seed/                  sample-data seeder
architecture/            executable architecture assertions

Domain roots are public composition boundaries. Public models, queries, and events are the deliberate cross-domain contracts; internal packages remain private. See the architecture guide before changing dependency direction.

About

An opinionated view on building a modular monolith in Go

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages