slog-multi composes Go slog handlers instead of replacing them
🚨 Design workflows of slog handlers: pipeline, middleware, fanout, routing, failover, load balancing...
At a glance
- What is it?
- slog-multi is a Go library that composes slog handlers, offering fanout, routing, first match, failover, load balancing, pipelines and error recovery as combinators over the standard library handler interface. Its own documentation warns that log processing is costly, and its test suite fuzzes every primitive.
- Who is it for?
- slog-multi suits a Go service that already writes structured logs and needs to send them somewhere else as well, or needs a different destination for errors than for the rest, since the primitives compose over the standard handler interface without replacing it. It is the wrong choice for a service with a single sink and no routing rules, where the standard library handler is enough and every extra stage is latency you own.
- 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 52 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 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Composition over the standard handler interface
slog-multi provides advanced composition patterns for Go's structured logging, so the question is what it adds to the standard library's slog.Handler. The answer is that slog itself gives you one handler and no way to combine them, and most production logging setups need more than one. A service often wants to write to a local file and to a collector, or wants errors to go somewhere different from debug output, and neither is expressible with the stock handler. This library provides the combinators for those arrangements while keeping the slog.Handler interface, which means the sinks it composes can be the standard JSON and text handlers, a third party handler such as the Zap, Zerolog or Logrus adapters, or your own. The GoDoc page is the primary documentation, and the package is installed with a single module fetch.
go get github.com/samber/slog-multiThe API is deliberately functional. A handler is composed by passing handlers to a constructor and wrapping the result, rather than by implementing an interface with many methods, so the tree of handlers you build reads like the routing you want.
Seven primitives for the arrangements people actually need
The feature list names seven composition strategies and each maps to a file in the repository. Fanout distributes logs to multiple handlers in parallel, for throughput and redundancy. Router conditionally routes logs based on custom criteria, with a separate module for predicates. FirstMatch routes to the first matching handler only, which is the cheapest way to express a priority order. Failover provides high availability logging with automatic fallback, so a dead collector does not take the local log with it. Load balancing distributes load across multiple handlers. Pipeline transforms and filters logs with middleware chains. Error recovery handles logging failures gracefully. On top of those there are two middleware helpers aimed at quick work, an inline handler for implementing a custom handler in a few lines and an inline middleware for transformation logic that does not deserve its own package. The examples directory has a runnable example for each of the six main primitives, including the pool example for load balancing, which is the fastest way to see what a given arrangement looks like in code.
Failure handling is the reason the library exists
Most of the primitives are ordinary combinators, and the interesting design question is what happens when a sink fails. With the standard library handler, a write to a broken writer is a write to a broken writer. That is fine for a file on local disk and questionable for a network collector, and it is the reason a failover primitive and an error recovery primitive both exist here. The recovery handler catches failures from downstream handlers so that a logging call in a request path does not become a request failure, and the failover handler tries one destination and moves to the next. The tradeoff is the obvious one: swallowing a logging error means the log entry is lost silently unless you look for it, so a team using these primitives should decide deliberately what happens to the records that could not be written. The repository separates this concern into its own modules, with error handling, failover and recovery each in their own file, which is a reasonable sign that the behaviour is meant to be read rather than guessed.
The library warns you about its own cost
The README carries a warning that is worth repeating here because most logging libraries do not say it. It tells users to use the library carefully because log processing can be very costly, and explains that excessive logging, with multiple processing steps and destinations, can introduce significant overhead, which is generally undesirable in performance critical paths. It adds that logging is always expensive and that sometimes metrics or a sampling strategy are cheaper, and closes with the reassurance that the library itself does not generate extra load. That last clause is a precise and useful statement. The overhead comes from the number of stages and destinations you wire up, not from the composition machinery, so the design question is how many sinks and how much transformation a given log line needs. A related library in the same family handles sampling policies, which is the natural companion for a team that finds itself paying for logs it does not read.
Every primitive has a fuzz target
The test suite is the most telling thing in the repository layout, because handler composition is exactly the kind of code where a nil handler or a mismatched context causes a panic in production. The top level contains fuzz test files alongside the unit tests, and the Makefile has a fuzz target that runs a dedicated fuzz function for each primitive, with the time controlled by a variable defaulting to ten seconds.
go test -fuzz=FuzzFanoutHandle -fuzztime=$(FUZZTIME) ./...
go test -fuzz=FuzzFailoverHandle -fuzztime=$(FUZZTIME) ./...
go test -fuzz=FuzzPoolHandle -fuzztime=$(FUZZTIME) ./...
go test -fuzz=FuzzFirstMatchHandle -fuzztime=$(FUZZTIME) ./...The rest of the toolchain is careful too. The test target runs the suite with the race detector enabled, the module depends on goleak for goroutine leak detection, which matters for a library that fans out to handlers concurrently, and there is a separate stress test file. Benchmarks are first class as well, with a benchmark target that runs with memory allocation reporting and a count of three, plus a watch variant driven by reflex for fast iteration, and the same watch pattern exists for tests. The library is developed inside a Go workspace, and it depends on the samber lo utility library and on a shared slog common package, which is where the shared attribute handling lives.
Version stability is promised up to 2.0
The README states that no breaking changes will be made to exported APIs before v2.0.0, and the current release line is 1.x, with v1.8.0 published on 2026-03-25 and v1.7.1 and v1.7.0 earlier in 2026. That is the kind of commitment that matters for a logging library, because a handler composition tree tends to end up spread across a codebase, and a breaking change in the middle of a release cycle is expensive. The licence is MIT, so vendoring the library into a closed source product is straightforward. One inconsistency is worth noting for anyone pinning versions. The README says compatibility is with Go 1.21 and above, while the module file declares a newer language version in its go directive, and the build badge advertises Go 1.22 or newer. The three statements do not agree, so check the module file against your toolchain rather than trusting the prose. The last push was on 2026-09-01, and the project is maintained as part of a wider family of slog adapters covering HTTP middlewares for Gin, Echo, Fiber, Chi and the standard library, handlers for Zap, Zerolog and Logrus, and sinks for a long list of collectors including Datadog, Sentry, Loki, Kafka, NATS and Parquet.
Editorial conclusion
slog-multi suits a Go service that already writes structured logs and needs to send them somewhere else as well, or needs a different destination for errors than for the rest, since the primitives compose over the standard handler interface without replacing it. It is the wrong choice for a service with a single sink and no routing rules, where the standard library handler is enough and every extra stage is latency you own. Verify three things before you adopt it: what the handler contract guarantees when a downstream sink fails, since the recovery and failover primitives exist precisely because the standard handler does not promise anything in that situation, whether your Go version is supported, because the README says compatibility with Go 1.21 and above while the module file declares a newer language version, and how much of your log volume can survive the extra processing, given the library's own warning about the cost of multi stage logging. The licence is MIT, the newest release is v1.8.0 from 2026-03-25, and the last push was on 2026-09-01.
Frequently asked questions
What does slog-multi add to the standard library slog handler?
It provides composition primitives over the slog.Handler interface: fanout to multiple handlers in parallel, conditional routing, first match routing, failover with automatic fallback, load balancing, pipelines of middleware, and error recovery. Sinks can be the standard JSON and text handlers or any third party handler.
Does slog-multi slow down my application?
The composition machinery itself does not add load, but the README warns that excessive logging with multiple processing steps and destinations introduces significant overhead in performance critical paths, and that logging is always expensive, with metrics or a sampling strategy sometimes being cheaper.
How do I install slog-multi?
With go get github.com/samber/slog-multi. The README states compatibility with Go 1.21 and above, while the module file declares a newer go version, and the build badge advertises Go 1.22 or newer, so check the module file against your toolchain.
Is the slog-multi API stable?
The README states that no breaking changes will be made to exported APIs before v2.0.0, and the current line is 1.x, with v1.8.0 published on 2026-03-25. The package is licensed under MIT.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/samber-slog-multi)Was this useful?