Skip to content

Research

This document may be outdated

This research was conducted during the initial design phase. The RFC-001 contains the most current analysis in §2 (Prior Art). Tool versions and project statuses may have changed since this was written.

The Problem

Go has no built-in tooling for multi-module monorepos. go.work is dev-only (can't be committed). replace directives break on publish. Sub-modules need prefixed tags. Every project solves this with shell scripts and tribal knowledge.

How Other Ecosystems Solved It

Rust

Cargo.toml with [workspace]. All crates in one workspace. cargo test tests everything. cargo-release handles version bumps, stripping dev-deps, publishing in dependency order, and tagging. Dev overrides ([patch]) don't leak into published crates — Cargo handles this automatically.

Node / TypeScript

npm workspaces or yarn workspaces. package.json in root with "workspaces": ["packages/*"]. Local packages auto-linked. changesets (community standard, 10k+ stars) handles version bumps, changelogs, npm publish, and tagging.

Java / Kotlin

Maven multi-module since 2005. Root pom.xml with <modules>. mvn release:prepare release:perform — bumps versions, tags, deploys to Maven Central. 20 years of polish.

Python

extras / optional dependencies. pip install mylib[otel] — user gets only what they need. No separate module required for optional deps.

Elixir

Umbrella projects. mix new --umbrella. {:dep, in_umbrella: true} automatically replaced with version on publish to Hex. The exact transformation we do manually with shell scripts.

Summary

ProblemRustNodeJavaPythonElixirGo
Workspace initCargo.tomlpackage.jsonpom.xmlpyproject.tomlmix.exsmanual go.work
Local deps in dev[patch] autoworkspaces autoparent POMpath depsin_umbrellamanual replace
Dev deps don't leak to publish✅ auto✅ auto✅ auto✅ auto✅ auto❌ manual strip
Release toolcargo-releasechangesetsmvn releasehatchmix hex.publish❌ none
Sub-module taggingcargo-releasechangesetsmvn releaseN/Amix❌ manual script
Optional deps without split[features]peerDeps<optional>extrasoptional❌ impossible

Go is the only major language where multi-module monorepo has no tooling support.

What Exists in Go

OTEL multimod

Internal tool (~3000 lines). Has verify, prerelease, tag. Requires manual versions.yaml config. Hardcoded for OTEL module paths. Not published as reusable tool. Supports "module sets" (groups with different versions) — overengineered for most projects.

kimono

Young project for Go monorepo management. Has module discovery and tag coordination. Unclear how well it handles strip replace / pin require. Worth watching.

AWS go-multi-module-repository-tools

Internal scripts including updaterequires for managing inter-module versions. Not designed for external use.

release-please (Google)

Generic release tool. Creates tags and changelogs. Doesn't understand Go replace directives. Requires manual per-module config.

goreleaser

For binaries, not libraries. Doesn't know about Go modules or multi-module.

gorelease (golang.org/x/exp)

Checks API compatibility between versions. Useful but orthogonal — checks "what to release", not "how".

Comparison

ToolDiscoveryStrip replacePin requireTagsVerifyZero-configReusable
OTEL multimod
kimono✅?✅?
AWS tools
release-please
goreleaseN/A
multimod

No existing tool fills all columns. The gap is real.

Industry Strategy

Large players avoid the problem entirely:

  • Google — Bazel, not Go modules
  • Uber, HashiCorp — single module, internal/ packages
  • Kubernetes — staging repos + publishing bot (10k lines of infra)

The absence of tooling causes the absence of multi-module projects, not the other way around.

Apache 2.0 · Built in public · Contributions welcome