Typhon wraps net/http so Monzo's RPC clients stop leaking bodies
A wrapper around Go's net/http to provide safety and convenience. At Monzo, Typhon forms the basis of most clients and servers in our microservices platform.
At a glance
- What is it?
- Typhon is Monzo's MIT licensed Go wrapper around net/http, adding automatic body closing, filters shared between clients and servers, context cancellation propagation and HTTP/2 support for the company's microservices platform.
- Who is it for?
- Adopt Typhon if you build Go services that talk to each other over HTTP and you want the same client and server plumbing that Monzo runs, especially automatic body closing and cancellation that propagates across service boundaries. Do not adopt it for a one off HTTP call, where the standard library is enough, and do not assume the dependency list is current, because the pinned golang.org/x/net version and the last tagged release both predate the most recent push.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 71 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A net/http wrapper that closes the body for you
Typhon is a wrapper around Go's net/http library, and the problem it was written for is stated plainly in the project documentation: forgetting to call body.Close() on a client request body is a common source of resource leaks in Go programs, so Typhon makes sure the body is closed automatically unless you are doing something unusual with it. That single behaviour is the clearest example of the design principle behind the library, which is to promote safety wherever it can. The second half of the story is that Typhon is not a toy. The documentation says it is used at Monzo to build RPC servers and clients across the company's microservices platform, and the repository layout backs that up: there are separate files for the server, the client, the service abstraction, filters, a router, request and response types, and an errors file, plus end-to-end test files for HTTP/1, HTTP/2 and benchmarks. That is the shape of a library used in production rather than a thin example wrapper.
Filters are decorators that compose on both sides
The middleware story in Typhon is called filters. Filters are decorators around Service objects, and the notable property is that servers and clients share common functionality by composing it in the same functional style. In practice that means the same filter can wrap an incoming server request and an outgoing client call, so a piece of behaviour such as propagation of a request identifier or injection of a tracing header is written once and applied on both legs of an RPC. The abstraction underneath is the Service interface, defined in service.go, which is what filters decorate, and the router in router.go sits above it to route requests to handlers. Because the same object type is used on both sides, a service handler written against Service can be reused as a client stub, which is what makes an RPC style library out of an HTTP wrapper.
Cancellation and errors are designed to cross the call stack
Two of the features matter most when your service calls other services. The first is propagation of cancellation. The documentation states that when a server has finished handling a request, the request context is automatically cancelled, and that these cancellations are propagated through the distributed call stack, letting downstream servers conserve work producing responses that are no longer needed. In other words, a client that goes away does not leave a trail of downstream calls still grinding away, and the mechanism is context cancellation rather than an application level timeout convention you have to remember to wire up. The second is error propagation. Responses carry an inbuilt Error attribute, and serialising and deserialising those errors into HTTP errors is handled automatically, with the documentation suggesting it be used together with monzo/terrors, which the go.mod file confirms as a direct dependency. The result is that a failure inside a downstream service can come back to the caller as a typed error rather than as an opaque 500 response.
HTTP/1.1, HTTP/2 and h2c behind one interface
Applications built with Typhon can talk over HTTP/1.1 or HTTP/2.0, and the library supports full duplex communication under HTTP/2.0, which is what lets a streaming request carry responses while the request body is still open. h2c, HTTP/2 over plain TCP without TLS, is also supported where a deployment needs it, and the repository has a dedicated h2c.go file for it, with platform specific files for the http package, http_darwin.go and http_linux.go, plus http_other.go as a fallback. The end-to-end tests are split the same way, with separate files for HTTP/1 and HTTP/2, which suggests the two protocol paths are exercised independently rather than assumed equivalent. For a service that is only ever called from a browser over TLS, none of this matters much. For an internal mesh where one service streams to another, it is the reason to pick this wrapper rather than the standard library.
The module, its dependencies and the example to read first
Typhon is a Go module published under the module path github.com/monzo/typhon, and its go.mod declares the Go version it expects:
module github.com/monzo/typhon
go 1.24The dependency list is short and tells you what the library leans on. There is monzo/terrors for the error type and monzo/slog for logging, golang.org/x/net for the HTTP/2 and h2c support, protobuf support through google.golang.org/protobuf and github.com/golang/protobuf, and test-only dependencies including testify, leaktest and the objx extension. That is a deliberately small surface for a networking library, and the vendor directory in the repository means the dependency set can be vendored into a build. The repository also ships an examples directory with a simple.go file, which is the fastest way to see the intended shape of a server and a client, and the test files, including prototest and legacyprototest directories, show how the protocol behaviour is pinned down. Note that the go.mod pins golang.org/x/net at v0.7.0, which is worth checking against your own dependency graph before you commit to it.
MIT terms and a release trail that slowed down
The code is MIT licensed, with the licence text in the LICENCE file at the repository root, which is the permissive end of the spectrum and means a company can take the library, change it and ship it without a copyleft obligation. The version history is where caution is warranted. Tagged releases include v1.1.8 on 2023-05-05, v1.1.9 on 2023-12-04 and v1.1.10 on 2024-09-23, and the last push to the repository was on 2026-08-12. So there has been work after the newest tag, but no new tag since September 2024. That is not the same as an abandoned project, and the build badge in the README still points at a CI job, but it does mean that if you pin to the latest release you are pinning to code from 2024, and if you track the master branch instead you are tracking an unreleased state. Whichever you pick, the practical cost of an upgrade is that your own tests, including the end-to-end ones, have to carry the change.
Editorial conclusion
Adopt Typhon if you build Go services that talk to each other over HTTP and you want the same client and server plumbing that Monzo runs, especially automatic body closing and cancellation that propagates across service boundaries. Do not adopt it for a one off HTTP call, where the standard library is enough, and do not assume the dependency list is current, because the pinned golang.org/x/net version and the last tagged release both predate the most recent push. Before you commit, read the filter and Service API in filter.go and service.go, check that your error type satisfies the Response Error attribute contract alongside monzo/terrors, and confirm the go.mod requirements still work with the Go 1.24 line the module declares.
Frequently asked questions
What does Typhon add on top of Go's net/http?
Typhon is a wrapper around net/http that closes client response bodies automatically, shares filter style middleware between servers and clients, encodes and decodes bodies to structs through its Request and Response types, propagates context cancellation across the distributed call stack, and carries an inbuilt Error attribute on responses. It supports HTTP/1.1, HTTP/2 with full duplex, and h2c.
Which Go version does Typhon need?
The go.mod file in the repository declares the module as github.com/monzo/typhon and specifies go 1.24. The dependency list includes golang.org/x/net, monzo/terrors, monzo/slog and protobuf libraries, and the repository carries a vendor directory for vendored builds.
How does Typhon handle errors from downstream services?
Responses have an inbuilt Error attribute, and the serialisation and deserialisation of those errors into HTTP errors is handled automatically. The documentation recommends using this together with monzo/terrors, which is a direct dependency in go.mod.
Where can I see a working Typhon server and client?
The repository contains an examples directory with a simple.go file, plus separate end-to-end test files for HTTP/1 and HTTP/2 and a prototest directory. The Service type in service.go is the interface that filters decorate and that routers route to, so those files together show how a server and a client are meant to fit together.