canonical
Start from the canonical path
If you are evaluating Plumego for real use, begin with the reference app and the documented default path before reading optional surfaces as if they were all equally mature.
Release Posture
Release posture, compatibility expectations, and the current support matrix.
Key highlights for this release. Full diff and tagged artifacts are on GitHub Releases.
3 more extension families promoted to beta
x/tenant, x/frontend, and x/messaging (app-facing service layer) completed two consecutive tagged refs (v1.0.0, v1.1.0) with no exported API changes, release-backed snapshots, and owner sign-off. Subordinate messaging primitives remain experimental.
Selected x/ai and x/data subpackages confirmed as beta surfaces
x/ai/provider, x/ai/session, x/ai/streaming, x/ai/tool, x/data/file, and x/data/idempotency have two release refs, API snapshots, and owner sign-off. Parent families remain experimental.
Agent workflow improvements
Route, diff-validation, task-bundle, recipe, and manifest guidance expanded so AI coding assistants find landing zones and validation paths more deterministically. internal/checks/cross-extension-deps validates forbidden imports against actual Go imports.
Website and bilingual docs synchronized
Release posture, status, architecture, migration, benchmark, and bilingual docs pages were synchronized and rebuilt. All 77 docs pages available in both English and Chinese.
The initial stable release on May 15, 2026. Full evidence in docs/release/v1.0.0.md.
9 stable roots reach v1 compatibility promise
core, router, contract, middleware, security, store, health, log, metrics — public API surface frozen. Breaking changes require a major version.
4 extension families promoted to beta
x/gateway, x/observability, x/rest, x/websocket completed two consecutive tagged refs with no exported API changes and owner sign-off.
Router now faster than Chi in sequential and parallel benchmarks
Phase 2 (pooled RouteState) and Phase 3 (FIFO cache, read-only RLock) reduced per-request allocation. Sequential: 4291 ns/op vs Chi's 4547 ns/op. Parallel: 663 ns/op vs Chi's 1013 ns/op.
Machine-readable control plane
specs/task-routing.yaml, specs/dependency-rules.yaml, and specs/change-recipes/ ship as first-class artifacts. AI coding assistants and CI share the same routing and boundary model.
This page exists to make compatibility boundaries explicit. It should help you distinguish what is safe to adopt through the canonical path, what is still evolving, and where release ambition is intentionally held back by policy or test depth.
canonical
If you are evaluating Plumego for real use, begin with the reference app and the documented default path before reading optional surfaces as if they were all equally mature.
matrix
The matrix is not marketing copy. It tells you which areas carry stronger compatibility expectations and which still require caution.
roadmap
A package can be interesting and actively developed without yet carrying the same stability promise as the stable roots.
Counts are synced directly from repository facts — not hand-copied. Use them as a quick orientation before reading the full support matrix.
Stable roots, supported reference surfaces, beta extensions, and experimental families are in the same repository but not at the same adoption risk level. The separation is load-bearing.
GA stable roots
Covered by the long-term v1 stable-root API promise and the first scope to evaluate for production services.
Supported reference
Kept aligned with the canonical path. Read as a guide, not as a reusable extension catalog.
Beta — promoted extensions
API frozen between minor release refs. Promoted after two tagged refs, snapshot comparison, and owner sign-off.
Experimental — extension families
Included in release scope and quality gates, but API compatibility is not frozen. Evaluate before adopting.
Most readers do not need every line of the support matrix first. They need a default decision posture: adopt the canonical path now, read supported reference surfaces as teaching tools, and treat experimental capability work as deliberate opt-in territory.
adopt now
If you are evaluating Plumego for production use, begin with stable library roots, the reference app, and the documented request path before expanding into optional surfaces.
evaluate with evidence
Seven extension families are promoted to beta — x/rest, x/websocket, x/gateway, x/observability (promoted at v1.0.0) and x/tenant, x/frontend, x/messaging (promoted at v1.1.0). Their exported API surfaces did not change across two consecutive tagged refs. Adopt them knowing the API is frozen between refs, not unconditionally.
evaluate deliberately
App-facing extension families outside the beta tier can be valuable today, but they should be adopted only after you understand where compatibility guarantees stop and where product-specific evolution is still expected.
wait for more evidence
If your service depends directly on subordinate extension primitives rather than on the owning family entrypoint, you should slow down until the discovery path and compatibility expectations are clearer.
The repository contains surfaces at several maturity levels at once. The point of this page is not to flatten them into one optimistic story, but to help you understand which surfaces should lead adoption and which ones should follow later with more caution.
ga stable roots
These are the compatibility-carrying library surfaces covered by the v1 stable-root promise. They set the bar for what Plumego expects most services to rely on over time.
supported reference
These surfaces are part of the official adoption path, but they should be read as guides for bootstrap and operational flow rather than as broad extension catalogs.
beta
Seven families completed the promotion checklist: x/rest, x/websocket, x/gateway, x/observability (v1.0.0), and x/tenant, x/frontend, x/messaging (v1.1.0). Two consecutive release refs, no exported API changes, release-backed snapshots, and owner sign-off.
experimental
These areas remain inside release scope and quality gates, but API and config compatibility are not frozen. They should be adopted for clear reasons rather than by default.
Release posture is framed by a few simple rules: the canonical path comes first, stable roots stay narrow, and optional capability families are allowed to move at different speeds.
default path
reference/standard-service and the stable-root path are the primary surfaces used to judge release readiness.
boundaries
Extension families are publishable, but they do not receive the same compatibility promise just by existing in the repository.
evidence
Policy, tests, examples, and docs are required before a surface should be treated as frozen for compatibility.
Upgrades are easiest when the release conversation stays attached to repository shape. Use the steps below as a practical order of operations whenever compatibility matters more than package curiosity.
01
Before upgrading, re-check whether your service still follows the canonical bootstrap, routing, and app-local wiring path.
02
Identify which surfaces your service imports directly and map them to stable, supported-reference, or experimental status.
03
When both surfaces are present, verify the stable roots and canonical path before evaluating experimental family changes.
04
Use the reference app, request-flow docs, and architecture page to verify that your local repository shape still matches the intended path.
The matrix below is synced from repository facts and is meant to be read as an adoption aid, not a branding grid.
| Area | Status | Compatibility Promise | Modules |
|---|---|---|---|
| Stable library roots | ga | Public package surface carries the v1 stable-root compatibility promise | contract, core, router, middleware, security, store, health, log, metrics |
| Canonical reference app | supported reference | Kept aligned with the canonical bootstrap and stable-root usage, but not treated as a reusable extension catalog | reference/standard-service |
| CLI | supported tool | Supported as a command-line tool, not as a Go import surface; command behavior and generated output must stay aligned with canonical docs | cmd/plumego |
| Beta extension families | beta | API surface frozen between minor release refs; promoted after two consecutive tagged refs with no exported API changes and owner sign-off | x/gateway, x/observability, x/rest, x/websocket, x/tenant, x/frontend, x/messaging |
| App-facing extension families | experimental | Included in repo quality gates and release scope, but API/config compatibility is not frozen | x/fileapi, x/openapi, x/resilience, x/rpc, x/data, x/ai, x/validate |
| Subordinate extension primitives | experimental | Maintained and tested, but discovery should start from the owning family entrypoint and compatibility is not frozen | x/ai/distributed, x/ai/filter, x/ai/instrumentation, x/ai/llmcache, x/ai/marketplace, x/ai/metrics, x/ai/multimodal, x/ai/orchestration, x/ai/prompt, x/ai/provider, x/ai/resilience, x/ai/semanticcache, x/ai/semanticcache/cachemanager, x/ai/semanticcache/embedding, x/ai/semanticcache/vectorstore, x/ai/session, x/ai/sse, x/ai/streaming, x/ai/tokenizer, x/ai/tool, x/data/cache, x/data/file, x/data/idempotency, x/data/kvengine, x/data/migrate, x/data/pgx, x/data/rw, x/data/sharding, x/data/sqlx, x/gateway/cache, x/gateway/discovery, x/gateway/ipc, x/gateway/protocol, x/gateway/protocolmw, x/gateway/transform, x/messaging/mq, x/messaging/pubsub, x/messaging/scheduler, x/messaging/webhook, x/observability/dbinsights, x/observability/devtools, x/observability/featuremetrics, x/observability/ops, x/observability/recordbuffer, x/observability/testlog, x/observability/testmetrics, x/observability/tracer, x/observability/windowmetrics, x/rpc/client, x/rpc/gateway, x/rpc/server |
A module does not become beta by declaration. It must complete a governed checklist: two consecutive tagged release refs with no exported API changes, release-backed API snapshots on record, and owner sign-off. The first four completed at v0.1.0–v0.2.0; the remaining three completed at v1.0.0–v1.1.0.
two release refs
Each promoted module was snapshotted at both refs using go run ./internal/checks/extension-release-evidence. No exported symbol changed.
snapshot comparison
Base and head snapshots for each module are checked into docs/evidence/extension/snapshots/ and compared automatically. Head-only snapshots do not clear the blocker.
owner sign-off
Module owners confirmed that the candidate meets the beta criteria in docs/reference/extension-stability-policy.md before the status field changed.
machine-readable ledger
specs/extension-beta-evidence.yaml records the release refs, snapshot paths, owner sign-off state, and open blockers for every candidate module.
x/rest
Owner: platform-api. Evidence: route registration, spec defaults, repository-backed controller, error semantics, pagination, offline example.
x/websocket
Owner: realtime. Evidence: hub lifecycle, stop idempotency, capacity errors, connection range iteration, broadcast after stop, leave no-op.
x/gateway
Owner: edge. Evidence: edge transport wiring, proxy configuration, route prefix handling, upstream balancing surface.
x/observability
Owner: observability. Evidence: exporter and tracer wiring, collector adapter surface, observability pipeline integration.
x/tenant
Owner: tenant. Promoted at v1.1.0. Evidence: JWT tenant identity, per-tenant quota evaluation, policy enforcement at transport layer, tenant lifecycle, isolation tests.
x/frontend
Owner: assets. Promoted at v1.1.0. Evidence: embedded and directory-based asset serving, cache-busting, pre-compressed delivery, directory safety, transport-layer attachment.
x/messaging
Owner: messaging. Promoted at v1.1.0 (app-facing family entrypoint). Evidence: queue and pubsub flow wiring, inbound webhook transport, scheduled job surface. Subordinate primitives remain experimental.
A release tag is not declared by naming a version — it is validated by a sequence of checks that must all pass together. Every check below is machine-executed, not a manual sign-off checklist.
race tests
go test -race -timeout 30s ./... runs across the full module tree. A release cannot proceed if any package has a race condition or failing test.
boundary check
go run ./internal/checks/dependency-rules rejects any import that crosses the stable-root boundary — whether the change came from a human or an AI coding agent.
module manifests
go run ./internal/checks/module-manifests verifies that each module has a module.yaml that matches the actual package surface before release.
reference layout
go run ./internal/checks/reference-layout confirms that reference applications follow the documented directory structure — main.go, internal/config, internal/app, internal/handler.
formatting
gofmt -l . must return an empty list. Code that is not formatted cannot enter the release scope, regardless of how it was authored.
# one command, all gates
make gates
# runs in order:
# gofmt -l .
# go run ./internal/checks/dependency-rules
# go run ./internal/checks/module-manifests
# go run ./internal/checks/reference-layout
# go test -race -timeout 30s ./...
Plumego optimizes for clarity and correctness, not raw throughput. These benchmarks measure the
dispatch cost of router.ServeHTTP against Go 1.22+ http.ServeMux with
PathValue() parameter extraction — the closest apples-to-apples comparison target in stdlib.
Results are medians across five three-second runs on a single machine.
Source: router/stdlib_bench_test.go — run with
go test -bench=BenchmarkCmp -benchmem -count=5 -benchtime=3s ./router/.
| Scenario | stdlib ns/op | stdlib B/op | plumego ns/op | plumego B/op | Ratio |
|---|---|---|---|---|---|
| Static route (3 routes registered) | 110 | 0 | 367 | 480 | 3.3× |
Single :param + read | 186 | 16 | 807 | 1,104 | 4.3× |
Two :param + reads | 332 | 48 | 870 | 1,112 | 2.6× |
Four :param deep path | 722 | 112 | 1,036 | 1,184 | 1.4× |
Wildcard *filepath + read | 392 | 56 | 813 | 1,112 | 2.1× |
| 70-route table (50 static + 20 param), cycled | 247 | 8 | 660 | 800 | 2.7× |
| Parallel static (GOMAXPROCS goroutines) | 119 | 0 | 313 | 480 | 2.6× |
| Parallel single param (GOMAXPROCS goroutines) | 128 | 16 | 1,029 | 1,104 | 8.0× |
| Method routing (5 HTTP methods, 1 param each) | 262 | 16 | 1,233 | 1,112 | 4.7× |
overhead source: context injection
Even a static route allocates ~480 B and 5 objects to build the per-request router context. This is unavoidable: the context stores route metadata, param slots, and the response contract helper regardless of whether params are present.
overhead source: param map build
The router collects param values during trie traversal, then builds a map[string]string before invoking the handler. Stdlib PathValue stores values lazily in the request's internal context, avoiding the map allocation until the first read.
overhead source: LRU cache contention
Each dispatch promotes the matched entry to the LRU front position. Under concurrent load this requires a write lock, serializing goroutines. The cache improves single-goroutine param throughput by ~20%, but adds contention at high concurrency. If param-heavy routes are under sustained high QPS, evaluate whether the cache benefit outweighs the contention cost.
numbers in context
At 1,000 req/s, 1 μs of router overhead consumes 1 ms/sec of CPU — well under 0.1%. Typical service handlers spend 1 ms–100 ms on I/O and business logic; the router's share is 0.001%–0.1% of request time. The cost is bounded and knowable. The rationale for this design is in Why Plumego.
# Go 1.26.0 · linux/amd64 · Intel Xeon @ 2.10 GHz
# 5 runs · 3 s each · medians reported
go test -bench=BenchmarkCmp -benchmem -count=5 -benchtime=3s ./router/ Maturity confirmed — the next step is implementation. Start from Getting Started, then copy from the reference app. For beta extensions, read the primer before importing.