# go-chassis/go-chassis: a Go microservice framework built around a handler chain

> go-chassis is a cloud native microservice framework for Go whose distinguishing mechanism is a handler chain that can inspect the result of the call it wraps. This review covers what it bundles, how to install it, and where its assumptions stop fitting.

**go-chassis/go-chassis** — a cloud native application framework for Go with rich eco-system

- Repository: https://github.com/go-chassis/go-chassis
- Stars: 2,727 · Forks: 471
- Language: Go
- License: Apache-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/go-chassis-go-chassis

## What go-chassis actually solves for a Go service team

A Go service that talks to other services ends up needing the same handful of things: a way to find the other service, a way to spread load across its instances, a circuit breaker so a slow dependency does not take you down, rate limiting, request routing, and some metric output. None of these are hard individually. The cost is in the assembly, and in the fact that the code for each one tends to end up inside your business logic.

go-chassis positions itself as the thing that already contains them. The README lists pluggable discovery (Service Center, Kubernetes), pluggable protocols (HTTP and gRPC by default), multiple servers separated by protocol and port, a handler chain, traffic marking, weight and match-rule based routing, retry, client-side load balancing, circuit breaking, rate limiting, Prometheus metric exposure, and OpenTracing integration. The intended audience is a team delivering Go microservices that wants those behaviours available by configuration rather than by writing them.

The design claim worth taking seriously is the handler chain. The README describes each handler as able to see the running result of the handler behind it and of the business logic. That is a stronger contract than a filter or an interceptor, which normally only sees the request on the way in. A circuit breaker needs the outcome, not the request, and so does a metric that records response status. The framework's argument is that this single extension point covers auditing, tracing span completion and status tracking without each of them being wired separately into your code.

## The handler chain and the invocation model

go-chassis is protocol-independent by design. The README states that any protocol can integrate with it and then use the same load balancing, circuit breaker, rate limiting and routing functions. The mechanism behind that is a standardized model: core/invocation/invocation.go defines the request representation that all protocols are converted into, so the middleware operates on one type regardless of whether the wire format was HTTP or gRPC.

That is the architecture in one sentence: protocol-specific server code turns an incoming request into an invocation, the handler chain runs around the business function, and the same chain runs on the client side around the outbound call. Because the chain wraps the call rather than sitting in front of it, a handler can act after the result exists. The README gives four uses for this: a circuit breaker checking command results, tracking response status for Prometheus, auditing selected responses, and completing an OpenTracing span after business logic has run.

Two consequences follow. First, anything you want to do around a call has an obvious place to live, and the framework's own middleware is written the same way you would write yours. Second, the invocation type is a contract you inherit. If your service needs a request shape that does not map cleanly onto it, you are working against the model rather than with it. The flexibility is real but it is the flexibility of a framework, not of a library you call from your own code.

## Installing go-chassis and getting a service to start

The README's get started section is three steps. First generate a module, then add the dependency, then follow the linked guide for writing an HTTP microservice. The version shown in the README is v2.0.4, while the most recent release listed for the repository is v2.8.0, so pin deliberately rather than copying the README string without thinking about it.

```bash
go mod init
go get github.com/go-chassis/go-chassis/v2@v2.0.4
```

If the module proxy is unreachable, the README gives a proxy override:

```bash
export GOPROXY=https://goproxy.io
```

After that, the README does not inline a full service example. It points to the documentation for writing your first HTTP microservice, and to the examples directory in the repository. Note the README's own warning: examples are migrating to the go-chassis/go-chassis-examples repository, so the examples/ tree in this repository may not be the current source of truth. The repository does contain examples/rest, examples/simple, examples/circuit, examples/ratelimit, examples/marker, examples/mutiports and others, plus an examples/docker-compose.yaml.

For debugging with dlv, the README documents a build tag rather than a runtime flag:

```bash
go build -tags debug -o server -gcflags "all=-N -l" server.go
```

The README explains that this custom debug tag exists to work around a Go and Delve interaction, and links the two upstream issues. If you debug with dlv and skip the tag, expect the problem those issues describe.

## Where the design puts friction: plugins, configuration and the extension split

The README says go-chassis has fewer dependencies on open source projects by default, and that more features come from plugins in the go-chassis/go-chassis-extension repository. Read the go.mod and that claim is visible: the direct requirements are a specific set, including go-restful, go-archaius, sc-client, openlog, seclog, opentracing-go and the Prometheus client libraries. The registry client for Service Center is an explicit dependency; other integrations are not.

The practical effect is that the framework is modular and the documentation has to be read per module. A feature you saw in the README may require a plugin that is not in the main module, and the README does not enumerate which is which. That is the first thing to check before planning an adoption, because it changes both your dependency graph and your upgrade surface.

Dynamic configuration is the second area where the README is thin. It states that configuration can be reloaded at runtime for load balancing, circuit breaker and rate limiting, powered by go-archaius, and links to a dynamic-conf page. It does not list the configuration keys here. If hot reload is part of your reason for choosing go-chassis, the key names and their semantics are something you will be reading out of the linked documentation, not out of this README.

A third friction point is the registry assumption. Discovery supports Service Center and Kubernetes, and the README says discovery can be disabled for end-to-end communication. But the API-first feature, which generates Open API 2.0 documentation and registers it to Service Center, is tied to that registry. Teams running purely on Kubernetes without Service Center should confirm what that feature does in their setup before counting on it.

## Limitations and cases where go-chassis is the wrong choice

The framework is opinionated about where resilience lives. Retry, client-side load balancing and circuit breaking are implemented in the process, in the client, through the handler chain. If your architecture already puts those concerns in a service mesh or an API gateway, you are duplicating them. The README notes that a service mesh can be introduced to a microservice system through servicecomb-mesher, which is a different deployment model: the mesh handles cross-language traffic at the network layer, while go-chassis handles it inside your Go process. Choosing both means deciding which layer owns which policy.

Language is the second boundary. This is a Go framework. The README's answer for polyglot systems is the mesh, not the framework. If most of your services are not Go, go-chassis applies to a minority of them and the mesh or gateway becomes the shared layer anyway.

Third, the release history is uneven. v2.7.0 is dated 2022-09-23, while v2.7.1 and v2.8.0 are both dated 2025-12-31. A team that adopted around the 2.7.0 timeframe spent roughly three years between feature releases. The repository itself is not archived and its last push was on 2026-08-24, so work continues, but anyone planning an upgrade cadence should look at the tag dates rather than assume a steady rhythm.

Finally, the handler chain is a framework contract. If your service is a small set of net/http handlers behind a proxy that already does the resilience work, adopting go-chassis means restructuring around the invocation model to gain features you have elsewhere. The cost is not the dependency; it is the shape of the code.

## How it compares with assembling Go middleware yourself

The realistic alternative is not a single competing framework. It is composing the pieces: a router such as go-restful or the standard library, a registry client, a circuit breaker library, a Prometheus client, and an OpenTracing or OpenTelemetry integration, wired together in your own code.

The difference in approach is where the seam sits. With composed libraries, each concern is a call you place in your handler, and the ordering and error handling are yours. With go-chassis, the concerns are handlers in a chain, and the framework defines when each runs and what it can see. The chain's ability to observe the result of the call is the concrete advantage of the framework approach, because a circuit breaker or a status metric written as a plain wrapper has to be threaded through every call site instead.

The trade is control over the dependency graph and the upgrade path. Composed libraries move independently; you upgrade the breaker without touching the router. go-chassis moves as a unit, and its plugin split means some features move in a separate repository. The README's point about fewer default dependencies is an acknowledgement of that trade, not a resolution of it.

There is also the Spring Cloud angle. The README states that go-chassis can work together with Spring Cloud through servicecomb, which matters if part of your system is Java. That is a specific integration path, and it is not the same as the mesh path; the two solve the polyglot problem at different layers.

## Maintenance, licensing and what to verify before adopting

The repository is not archived. Its last push was on 2026-08-24, and the most recent release listed is v2.8.0 from 2025-12-31. Releases before that are v2.7.1, also dated 2025-12-31, and v2.7.0 from 2022-09-23. The gap between v2.7.0 and v2.7.1 is the number to keep in mind when you plan upgrades, because it is longer than most teams assume from a project with this much surface area.

The licence is Apache-2.0, and the repository carries both a LICENSE and a NOTICE file. Apache-2.0 is permissive and includes an explicit patent grant, and the NOTICE file is the mechanism the licence uses for attribution of bundled or derived work. If you redistribute a binary built with go-chassis, the NOTICE file is the artifact to look at, and the go.sum and licenses/ directory in the repository show the transitive picture. None of this is legal advice; the point is that the attribution obligation is not zero and the files to satisfy it are in the repository.

Upgrade cost is dominated by the plugin boundary. A version bump can change the main module while the extension repository moves separately, so a pin should cover both. The README also documents a debug build tag that exists to work around an upstream Go and Delve issue, which is the kind of workaround that can disappear or change between Go versions; verify it still applies on the Go release you build with.

## Conclusion

Adopt go-chassis if you are building Go services that need client-side load balancing, circuit breaking, rate limiting and Prometheus metrics without assembling those pieces yourself, and if you accept its handler chain and registry model as the shape of your code. Do not adopt it if your services are plain net/http handlers that call a sidecar or an external gateway for resilience, because you would be importing a framework to use a fraction of it. Before committing, verify two things against the version you pin: whether the registry plugin you intend to use lives in the main module or in go-chassis-extension, and whether the dynamic configuration keys you rely on are documented for that release. The examples directory is migrating to go-chassis-examples, so check the destination repository rather than assuming examples/ is current.

## FAQ

### What is the main purpose of go-chassis?

The README describes it as a microservice framework for rapid development of microservices in Go, focused on delivering cloud native applications more easily. It bundles discovery, load balancing, circuit breaking, rate limiting, routing, metrics and tracing behind a handler chain so those behaviours do not have to be written into business logic.

### How do I install go-chassis in a Go module?

The README's get started section runs go mod init, then go get github.com/go-chassis/go-chassis/v2@v2.0.4, and points to the documentation for writing your first HTTP microservice. If the module proxy is unreachable it suggests setting GOPROXY to https://goproxy.io.

### Does go-chassis support gRPC as well as HTTP?

Yes. The README states that go-chassis supports two communication protocols, HTTP and native gRPC, and that it brings circuit breaker and route management to gRPC. It also says the framework is protocol-independent, so other protocols can integrate and reuse the same features.

### Which service registries does go-chassis work with?

The README lists pluggable discovery supporting Service Center and Kubernetes, covering both client side and server side discovery patterns, and notes that discovery can be disabled to use end to end communication. The API-first feature that registers Open API 2.0 documents is tied to Service Center.

### Is go-chassis still maintained?

The repository is not archived and its last push was on 2026-08-24. The most recent release listed is v2.8.0 from 2025-12-31, but the release before that line, v2.7.0, is dated 2022-09-23, so the cadence has not been uniform.

### What licence does go-chassis use?

The repository is licensed under Apache-2.0 and includes both a LICENSE and a NOTICE file at the top level, along with a licenses/ directory covering dependencies.

## Sources

- [go-chassis/go-chassis on GitHub](https://github.com/go-chassis/go-chassis)
- [Issues](https://github.com/go-chassis/go-chassis/issues)
- [License: Apache-2.0](https://github.com/go-chassis/go-chassis/blob/master/LICENSE)
- [README](https://github.com/go-chassis/go-chassis/blob/master/README.md)
- [Releases](https://github.com/go-chassis/go-chassis/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/go-chassis-go-chassis
