Service Runner: Simple Safe Modular

A tiny Go library for composing service modules with a clean lifecycle.

go get github.com/go-srvc/srvc@latest

Why srvc?

Real services run multiple long-lived components (HTTP, DB, signals, telemetry). Wiring up their startup order, graceful shutdown, panic recovery, and error reporting by hand is repetitive and easy to get wrong.

One small interface

Every module implements Init, Run, Stop, and ID. The runner sequences and supervises them so your main stays a list of components.

Safe shutdown

Panics are recovered. Errors from Init, Run, and Stop are aggregated. Stop runs in reverse order on every initialised module, even when something failed mid-flight.

Zero deps in core

The srvc package is standard library only. Pull in just the modules you need from go-srvc/mods: HTTP, SQL, OpenTelemetry, signals, tickers.

No zombie services

When any Run returns, the whole service shuts down. Pair with sigmod for clean SIGINT and SIGTERM handling, and let RunAndExit drop the exit code.

Lifecycle, visualized

Four modules going through srvc's lifecycle under different scenarios. One row plays at a time; hover any row to lock the animation to it.

Clean shutdown

Signal triggers shutdown. Modules stop in reverse order.

Init error

M3's Init fails. M1 and M2, the already-initialised modules, get Stop in reverse. M4 never starts.

Panic recovery

M3 panics during Run. The panic is recovered as an error and the rest shut down gracefully.

A practical example

A full HTTP service with structured logging via OpenTelemetry, distributed tracing, a Postgres pool, and graceful shutdown on SIGINT. Modules compose, the runner supervises, your main stays declarative.

package main

import (
	"fmt"
	"net/http"
	"os"

	"github.com/XSAM/otelsql"
	"github.com/go-srvc/mods/httpmod"
	"github.com/go-srvc/mods/logmod"
	"github.com/go-srvc/mods/sigmod"
	"github.com/go-srvc/mods/sqlxmod"
	"github.com/go-srvc/mods/tracemod"
	"github.com/go-srvc/srvc"
	semconv "go.opentelemetry.io/otel/semconv/v1.30.0"

	_ "github.com/jackc/pgx/v5/stdlib"
)

func main() {
	db := sqlxmod.New(
		sqlxmod.WithOtel("pgx", os.Getenv("DSN"),
			otelsql.WithAttributes(semconv.DBSystemNamePostgreSQL),
		),
	)
	srvc.RunAndExit(
		logmod.New(),
		tracemod.New(),
		sigmod.New(os.Interrupt),
		db,
		httpmod.New(
			httpmod.WithAddr(":8080"),
			httpmod.WithHandler(handler(db)),
		),
	)
}

func handler(db *sqlxmod.DB) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var version string
		if err := db.DB().GetContext(r.Context(), &version, "SELECT version()"); err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		fmt.Fprintf(w, "db version: %s\n", version)
	})
}

srvc

Package overview, exported API, and runnable examples extracted from the latest tagged release.

v0.2.0

Mods catalog

Ready-made modules for HTTP, SQL, OpenTelemetry, signals, and tickers. Pick a tagged release on each mod's page.

8 modules