# thejerf/suture: Context-Aware Supervisor Trees for Go

> thejerf/suture brings Erlang-style supervisor trees to Go through a context-based service interface. It is aimed at Go developers who need controlled restarts, shutdown handling, and logging around long-running services, but service shutdown still belongs to the service implementation.

**thejerf/suture** — Supervisor trees for Go.

- Repository: https://github.com/thejerf/suture
- Stars: 1,413 · Forks: 77
- Language: Go
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/thejerf-suture

## Why Suture exists in a Go service stack

Suture addresses the problem of supervising long-running pieces of Go code. The README describes its model as Erlang-ish supervisor trees: a parent service owns child services, observes when they stop, and can restart them according to supervisor policy. This is useful when a program has workers, listeners, or other components that can fail independently and need to be brought back into service without making the surrounding application responsible for every restart decision.

The library is for Go developers who already have services with a defined lifetime and need a parent process to coordinate that lifetime. It is not a general job scheduler, and the README does not describe it as a replacement for ordinary goroutine management. Its scope is narrower and more structural. The service code remains ordinary Go code, while Suture supplies the supervision layer around it.

That distinction matters for adoption. A simple program that starts one worker and exits when it fails may not need a supervision tree. A server with several components that need restart policy, coordinated shutdown, and operational visibility is a better fit. The README specifically calls out failure cases such as services repeatedly dying and consuming CPU through endless restarts, so the intended benefit is controlled supervision rather than simply restarting code as fast as possible.

## The v4 service and supervisor contract

The major v4 change is the move to contexts. The README states that v4 was rewritten to work with `context.Context`, and it highlights the central interface as `Serve(ctx context.Context)`. A library does not need to import Suture to expose that interface. That means a service can be written and used independently, while a Suture supervisor can also manage it.

The design is Erlang-inspired, but the Go implementation does not require service code to become an OTP process or adopt an Erlang runtime. The parent supervisor starts services, watches their termination, and applies its supervision behavior. The README also points to structured logging support through a separate package, `github.com/thejerf/sutureslog`, which supplies a default `slog`-based logger. Keeping that logger in a separate Go module avoids making the main `suture/v4` module depend on a minimum Go version associated with `slog`.

The service interface has an important operational implication. Passing a context does not automatically make a service correct. The service must actually stop when cancellation reaches it. The README's Go 1.25 `synctest` guidance makes this boundary explicit: when shutdown leaves Suture goroutines blocked, the stack trace points to a service that is not shutting down.

## Installing Suture and preparing logging

The README gives the module import path but does not provide a complete installation command for Suture itself. It also says that the `slog` integration is separate and must be obtained as another module. A project can therefore add the documented import to its Go source, while the exact module retrieval and version selection remain dependent on the project's Go toolchain and dependency management process.

The README explicitly gives this additional command for the optional logging module:

```bash
go get github.com/thejerf/sutureslog
```

That command is not needed for the basic supervisor package described in the README. It applies when the application wants the default `slog`-based logger. The main v4 import is:

```go
import "github.com/thejerf/suture/v4"
```

The project uses semantic versioning and Go modules. Version 4 is the context-aware rewrite. The README says v3 and earlier remain documented and supported for now, while v4 is the recommended version for new users. There is no homepage or GitHub release listed in the repository information, and the README points readers to the v4 package documentation for the full API and examples.

## A first supervised service with context cancellation

The README does not include a complete runnable program for constructing a `Supervisor`, registering a concrete service, or choosing restart parameters. It does document the service contract that a first use depends on: start the supervisor through `.Serve(ctx)`, and provide a context that is cancelled within the enclosing `synctest.Test` function when testing shutdown.

The README identifies the service method used to start a supervised component as `Serve(ctx)`. In a real service implementation, the context should be passed into the work that can block or wait. Suture can cancel it during shutdown, but the service must observe that cancellation and return. The README does not specify a universal service template, so inventing registration fields or restart options would misrepresent the project. The appropriate first use is therefore to consult the v4 package documentation for the exact supervisor construction API, then verify that the service returns after its context is cancelled.

The README's testing guidance is particularly concrete. It says the context used to start the supervisor must be cancelled within the `synctest.Test` function because the test context itself is cancelled too late. If the test ends with `panic: deadlock: main bubble goroutine has exited but blocked goroutines remain`, inspect the Suture shutdown goroutines and the service goroutine below them. The service stack identifies where it is stuck.

## Restart behavior and failure-mode boundaries

Suture is designed to deal with real supervision failures rather than blindly restarting dead services. The README calls out the danger of burning all available CPU by endlessly restarting a service. That implies the supervisor is intended to manage restart behavior rather than treating every return as an event to repeat without limit. The exact thresholds and policies are not described in the README, so they should be taken from the v4 package documentation and source rather than inferred from the project name.

A second failure boundary concerns error classification. The 4.0.6 changelog says that returning `context.Canceled` or `context.DeadlineExceeded` could previously be interpreted as evidence that the service's context had ended. The revised behavior examines the context directly. This matters because a service may return a context-related error originating from another context while its supervisor context is still active. The change is documented as a bugfix with a possible behavioral effect.

There is also a clear distinction between supervisor shutdown and service shutdown. If a service ignores cancellation, Suture may remain blocked waiting for it to stop. Suture does not make an uncooperative service cooperative. That makes it a poor choice for code that owns non-cancellable OS operations or workers that never return, unless the application adds its own shutdown mechanism.

## Suture against direct goroutine management

The README itself names the main alternative: an application can use `go yourthing.Serve(ctx)` directly. Direct goroutine management is simpler for one service or a small set of services with straightforward lifecycle requirements. It avoids introducing a supervisor abstraction and does not require a policy for restarts or parent-child failure handling.

Suture takes a different approach. It provides a supervision tree with a service contract based on `Serve(ctx context.Context)`, restart behavior, shutdown coordination, and hooks for logging. Its advantage is structural consistency when several services need to be managed as a group. The cost is an additional lifecycle model and a stricter expectation around cancellation. A service that merely has a goroutine and a stop function may fit a smaller home-grown supervisor better.

The project also separates logging into `github.com/thejerf/sutureslog`. That separation keeps the core package from taking on the Go version requirement associated with `slog`, but it means users who want the default logger must manage a second module. This is a packaging trade-off, not evidence that the core library requires `slog` for operation.

## Conclusion

Adopt Suture when a Go application needs a supervisor around services that accept context and can terminate when that context is cancelled. Do not adopt it as a substitute for making services themselves stoppable, and verify first that your services honor cancellation, especially under Go 1.25 synctest. For existing v3 users, upgrading to v4 is a behavioral and interface change rather than a drop-in dependency update.

## FAQ

### What is thejerf/suture used for in Go?

It provides Erlang-style supervisor trees for supervising Go services. The v4 design uses a context-aware `Serve(ctx context.Context)` interface and coordinates service lifecycle behavior.

### Does thejerf/suture use context cancellation?

Yes. Version 4 was rewritten around `context.Context`, and the README recommends v4 for new users. Services still need to observe cancellation and shut down correctly.

### How do I add slog logging to thejerf/suture?

The README documents the separate `github.com/thejerf/sutureslog` module, which provides a default `slog`-based logger. It must be obtained separately with `go get github.com/thejerf/sutureslog`.

## Sources

- [Issues](https://github.com/thejerf/suture/issues)
- [License: MIT](https://github.com/thejerf/suture/blob/master/LICENSE)
- [README](https://github.com/thejerf/suture/blob/master/README.md)
- [thejerf/suture on GitHub](https://github.com/thejerf/suture)

---

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