Skip to main content

servicewright

One Host, many Entrypoints — a batteries-optional microservice runtime for async Python.

PyPI Python License CI codecov Docs

Describe a service once as an AppSpec (DI container, lifecycle, observability, warmup, health) and run it through any number of pluggable entrypoints — HTTP, gRPC, scheduler, background daemon, one-shot batch — under one unified lifecycle. The "API vs worker" distinction does not exist at the core: a cron job and an HTTP request are the same thing — one unit of work in a fresh DI scope.

This is the model behind .NET Generic Host, Spring SmartLifecycle and go-kratos transport.Server, adapted to async Python.

Why

  • One lifecycle for every archetype: Bootstrap → Warmup → Ready → Serve → Drain → Cleanup. Kubernetes-correct shutdown out of the box: readiness flips to false before draining, every entrypoint finishes in-flight work within a grace window, the DI scope closes last, and a service that dies mid-serve exits non-zero instead of looking like a graceful stop.
  • DI-agnostic two-tier scopes: the core depends on no DI library. AppScope holds process-lifetime singletons; a fresh UnitScope wraps every request / RPC / job / message. A dishka adapter ships in the box; any container fits by implementing two methods.
  • Pluggable observability add-ons: metrics / tracing / logging / error-tracking are protocols in the kernel with selectable, extra-gated backends (prometheus, OpenTelemetry, Sentry, structlog). Adding a backend = one module + one register_sink call, zero core changes.
  • One error taxonomy, every transport: a ServiceError raised in business code renders as an RFC 9457 problem document over HTTP and as the mapped grpc.StatusCode over gRPC, with one masking rule for non-public details and a pluggable renderer when you own the wire format.
  • Zero hard dependencies: pip install servicewright brings pure Python. Every framework binding lives behind an extra; the kernel never imports an SDK, a vendor, or a transport.

Installation

pip install servicewright                    # pure kernel, zero dependencies
pip install "servicewright[fastapi]"         # + FastAPI/uvicorn entrypoint
pip install "servicewright[grpc]"            # + gRPC entrypoint
pip install "servicewright[apscheduler4]"    # + cron/scheduler entrypoint
pip install "servicewright[metrics,observability,sentry]"  # + prometheus, otel+structlog, sentry
pip install "servicewright[uvloop]"          # + uvloop, picked up by run_sync(loop="auto")
pip install "servicewright[all]"             # everything except the conflicting [apscheduler3]

Requirements: Python 3.12+

Quick start — HTTP API + cron in ONE process

from servicewright import AppSpec, ObsConfig, ObservabilityManager, Service, run_sync
from servicewright.adapters.apscheduler4 import ScheduledJob, SchedulerEntrypoint
from servicewright.adapters.fastapi import FastApiEntrypoint


def build_service() -> Service:
    spec = AppSpec(
        service_name="orders-service",
        create_container=build_container,   # your DI container factory
        observability=ObservabilityManager(
            ObsConfig(metrics="prometheus", tracing="otel", logging="structlog"),
        ),
    )

    http = FastApiEntrypoint(routers=(router,))          # kind="http"
    cron = SchedulerEntrypoint(jobs=[                    # kind="scheduler"
        ScheduledJob(id="sweep", func=sweep_expired_orders, trigger=interval_trigger),
    ])
    return Service(spec, entrypoints=[http, cron])


if __name__ == "__main__":
    run_sync(build_service(), Settings())   # loop="auto": uvloop when installed, asyncio otherwise

Both entrypoints share one DI container, one observability setup and one graceful shutdown. Scaling the worker separately later = the same AppSpec in a second process with a different entrypoint list.

Entrypoints

Archetype Adapter Extra
HTTP API adapters.fastapi / adapters.litestar fastapi / litestar
gRPC API adapters.grpc grpc
Scheduled / cron adapters.apscheduler4 / adapters.apscheduler3 apscheduler4 / apscheduler3
Background daemon DaemonEntrypoint (built-in) —
One-shot / batch OneShotEntrypoint (built-in) —

Writing your own entrypoint = implementing four methods (bind, serve, drain, stop) with nothing installed.

What's inside

The kernel is core/; everything that touches a third-party SDK is an extra-gated adapter. An import-linter contract enforces the direction in CI: deleting adapters/ leaves core/ importable.

Module Responsibility Extra
servicewright AppSpec, Service, Host, run, run_sync — the public vocabulary —
core.contracts Entrypoint, Plugin, container/settings/health protocols —
core.aio.host The lifecycle kernel: warmup → ready → serve → drain → cleanup —
core.errors ServiceError, ErrorKind, RFC 9457 renderer + renderer seam —
core.context Transport-neutral correlation store + outbound propagation —
core.health HealthRegistry driving both HTTP routes and the gRPC health service —
core.warmup Priority-grouped, fail-fast warmup before readiness flips —
core.observability Sink protocols, NullObjects, backend registry, redaction —
adapters.builtin DaemonEntrypoint, OneShotEntrypoint — zero-dependency —
adapters.fastapi FastAPI entrypoint, middleware stack, problem-details handlers, its config as settings models fastapi
adapters.litestar Litestar entrypoint litestar
adapters.grpc gRPC entrypoint over grpc-server-kit, error mapping, health bridge grpc
adapters.apscheduler4 / apscheduler3 Scheduler entrypoints with identical public surfaces apscheduler4 / apscheduler3
adapters.dishka dishka ⇄ core scope binding dishka
adapters.settings pydantic-settings models of the settings contract settings
adapters.observability prometheus / OpenTelemetry / Sentry / structlog / stdlib sinks see below
adapters.warmers, adapters.health Redis / Postgres / Kafka warmers and checks redis, postgres, kafka
servicewright.testing FakeContainer, FakeEntrypoint, FakeScope, FakeSettings —

Optional dependencies

Extra Pulls in Enables
fastapi fastapi, uvicorn, deadline-budget, prometheus-fastapi-instrumentator FastApiEntrypoint + its middleware stack, HttpServerSettings
litestar litestar, uvicorn LitestarEntrypoint
grpc grpc-server-kit[reflection,channelz,health] GrpcEntrypoint, error mapping, health bridge
apscheduler4 / apscheduler3 apscheduler 4.x / 3.x SchedulerEntrypoint (one major per environment)
dishka dishka DishkaContainer
settings pydantic-settings BaseServiceSettings + the four section models, with the sinks' defaults
observability opentelemetry-sdk, OTLP gRPC exporter, structlog otel tracing + structlog logging sinks
fastapi-tracing the above + opentelemetry-instrumentation-fastapi HTTP request spans
metrics prometheus-client prometheus metrics sink + /system/metrics
sentry sentry-sdk sentry error-tracking sink
redis / postgres / kafka redis / sqlalchemy / aiokafka matching warmers and health checks
uvloop uvloop the uvloop event loop, picked by run_sync(loop="auto" | "uvloop")
all everything except apscheduler3 the full runtime

Examples

Runnable, self-contained scripts (each exits 0):

Documentation

Full documentation: bedrock-python.github.io/servicewright

For AI agents the whole library on one page, written for a coding assistant
Your first service a complete service with nothing installed but the kernel
Tutorial an HTTP API and a cron job in one process
Architecture the six nouns, the two layers, the dependency rule
Lifecycle phase order, budgets, signals, exit codes
Adapters FastAPI, Litestar, gRPC, scheduler, dishka, observability backends
Blueprints copy-paste skeletons: project layout, HTTP API, gRPC, worker, batch job
Writing an entrypoint four methods, worked end to end
Kubernetes probes, grace periods, exit codes
Runbooks symptom → cause → fix
API reference generated from the source

The design source-of-truth lives in ARCHITECTURE.md.

License

Apache 2.0 — see LICENSE.

Metadata

Release files for servicewright 0.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for servicewright 0.13.0
File Size Uploaded
servicewright-0.13.0.tar.gz 124.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for servicewright 0.13.0
File Interpreter ABI Platform
servicewright-0.13.0-py3-none-any.whl Python 3 none any Details

Total release size: 306.4 kB

Release files / servicewright-0.13.0.tar.gz

Download URL servicewright-0.13.0.tar.gz
Size 124.1 kB
Tags Source
SHA-256 checksum
How to use checksums
604a3872ada370d4fcda5485a1b76b63d4bf13f97843cc73ca5f0ee524cc736e
BLAKE2b-256 checksum
How to use checksums
21ac11fb0b0f6a162a0064621a9977ebe22e7adc0d3016e5138423665372563a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / servicewright-0.13.0-py3-none-any.whl

Download URL servicewright-0.13.0-py3-none-any.whl
Size 182.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f7181e9a1d53abf3497f90c0e93427fa9ea6f2ebc2ce4c522582a90d0f0ddee7
BLAKE2b-256 checksum
How to use checksums
0589e949a86021add246f2ecd80a36a0ce7e3d9fdeeed0a9da307b7a18fe113f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

0.13.1

2 release files

This release

0.13.0 This release

2 release files

0.12.0

2 release files

0.11.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page