Skip to main content

grpc-server-kit

Batteries-optional async gRPC server toolkit (app facade, builder, TLS, lifecycle, health, interceptors, observability)

PyPI Python License CI codecov Docs

grpc-server-kit gives you a clean, production-grade foundation for building grpc.aio servers: a one-object GrpcApp facade, validated channel options, TLS/mTLS credential loading, graceful signal-driven shutdown, streaming-aware interceptors, and gRPC health checking — with optional extras for reflection, channelz, Prometheus metrics, OpenTelemetry tracing, Sentry, Dishka DI, and typed pydantic settings.

The core depends only on grpcio. Every integration is an opt-in extra, so you install exactly what you use.

Installation

pip install grpc-server-kit                      # core (grpcio only)
pip install "grpc-server-kit[settings]"          # + pydantic settings models
pip install "grpc-server-kit[health]"            # + gRPC health checking
pip install "grpc-server-kit[metrics,tracing]"   # + Prometheus + OpenTelemetry
pip install "grpc-server-kit[all]"               # everything

Requirements: Python 3.12+

Quick start

import asyncio

from grpc_server_kit import GrpcApp

app = GrpcApp(port=50051)
app.add_servicer(MyServicer(), add_MyServiceServicer_to_server)

asyncio.run(app.run())   # build + bind + SIGINT/SIGTERM + graceful shutdown

That's the whole server. GrpcApp builds the grpc.aio server, binds the port (TLS-aware), installs signal handlers, and serves until termination. More knobs when you need them:

from grpc_server_kit import GrpcApp, GrpcServerConfig
from grpc_server_kit.aio.interceptors import (
    AsyncContextInterceptor, AsyncExceptionHandlerInterceptor,
    AsyncMetricsInterceptor, AsyncRequestLoggerInterceptor, HeaderConfig,
)
from grpc_server_kit.observability.metrics import get_grpc_server_metrics

config = GrpcServerConfig(host="[::]", port=50051, grace_period=10.0)   # stdlib dataclass
app = GrpcApp(config, interceptors=[
    AsyncMetricsInterceptor(metrics=get_grpc_server_metrics(), service_name="my.pkg.MyService"),
    AsyncContextInterceptor([HeaderConfig("x-request-id", "request_id")]),
    AsyncRequestLoggerInterceptor(),
    AsyncExceptionHandlerInterceptor(MY_ERROR_STATUS_MAP),   # domain error → gRPC status
])
app.add_servicer(MyServicer(), add_MyServiceServicer_to_server)
app.enable_health(checkers=[DatabaseHealthChecker(session_maker)])   # [health] extra
app.enable_reflection(["my.pkg.MyService"])                          # [reflection] extra

asyncio.run(app.run())

Prefer pydantic-validated, env-friendly settings? Use grpc_server_kit.settings.BaseGrpcServerSettings (the [settings] extra) — GrpcServerConfig and BaseGrpcServerSettings are interchangeable everywhere the kit accepts settings.

Streaming-aware interceptors

Every interceptor wraps the whole RPC for all four call kinds — unary-unary, unary-stream, stream-unary, stream-stream. Durations cover the full stream, errors raised mid-stream are mapped to proper gRPC statuses, and cleanup always runs. Write your own by implementing a single async-generator hook:

from grpc_server_kit.aio.interceptors import AsyncServerInterceptor, RpcCall

class TimingInterceptor(AsyncServerInterceptor):
    async def around_call(self, call: RpcCall):
        start = time.perf_counter()
        try:
            yield                      # the RPC (or the full response stream) runs here
        finally:
            log.info("%s took %.3fs", call.method_name, time.perf_counter() - start)

Canonical chain order (outermost first): metrics → context → logger → tracing → exception handler → sentry. The exception handler maps exception types to gRPC statuses over the MRO and sends safe, non-leaking details; deliberate context.abort() calls pass through untouched. Sentry sits inside the exception handler so it observes raw handler exceptions before they become aborts (outside it would never capture anything), with a capture filter that reports only server-class errors.

Advanced API

GrpcApp is sugar over small, composable pieces you can use directly — for DI containers, custom lifecycles, or embedding:

from grpc_server_kit import bind_server_port
from grpc_server_kit.aio import AsyncGrpcServerBuilder, run_async_grpc_server

server = (
    AsyncGrpcServerBuilder(settings)
    .with_interceptors(interceptors)
    .with_servicers(lambda s: add_MyServiceServicer_to_server(MyServicer(), s))
    .with_reflection(["my.pkg.MyService"])
    .build()
)
bind_server_port(server, settings)            # honors settings.ssl_enabled (TLS/mTLS)
await run_async_grpc_server(server, address=f"{settings.host}:{settings.port}")

Dishka DI providers (cut the per-service boilerplate)

If your service uses Dishka, the kit ships ready-made providers so you register a handful of providers instead of hand-writing the interceptor list, settings aliasing, and a metrics provider. grpc_server_providers(...) bundles the standard set in one call:

from dishka import make_async_container
from grpc_server_kit.dishka import GrpcioProvider, FromDishka, inject
from grpc_server_kit.aio.dishka import grpc_server_providers
from grpc_server_kit.aio.server import AsyncServer
from grpc_server_kit.aio import run_async_grpc_server
from grpc_server_kit import bind_server_port

container = make_async_container(
    *grpc_server_providers(                       # settings + metrics + sentry/tracer seams
        settings.grpc,                            # + the canonical interceptor chain + AsyncServer
        service_name="my.pkg.MyService",
        error_status_map=MY_ERROR_STATUS_MAP,     # service-specific domain map (optional)
        metrics_enabled=settings.grpc.metrics_enabled,
    ),
    GrpcioProvider(),                             # request-scoped ServicerContext for FromDishka
    MyDomainProvider(),                           # your use-cases / repos
)

server = await container.get(AsyncServer)         # interceptors + options already wired
add_MyServiceServicer_to_server(MyServicer(), server)   # AsyncServer works directly
bind_server_port(server, settings.grpc)
await run_async_grpc_server(server, address=f"{settings.grpc.host}:{settings.grpc.port}")

The interceptor chain is built in the canonical order (metrics → context → logger → tracing → exception → sentry → DishkaAioInterceptor), with include_* toggles and extra_outer / extra_inner slots on GrpcServerInterceptorsProvider. Providers degrade gracefully: the metrics / Sentry / tracer seams resolve to None when disabled or their extra is absent, and the interceptors no-op. SDK initialization (sentry_sdk.init, OpenTelemetry setup, the /metrics HTTP server) is a process-wide concern and is not done by these providers. Requires [dishka] (+ [metrics]/[sentry]/[tracing] for those seams).

Granular providers (GrpcServerSettingsProvider, PrometheusGrpcServerMetricsProvider, SentryAdapterProvider, TracerAdapterProvider, GrpcServerInterceptorsProvider, AsyncGrpcServerProvider) are available for finer control.

What's inside

Layout convention: all async code lives under a single grpc_server_kit.aio package (mirroring grpc.aio), organized by domain (aio.health, aio.interceptors, aio.observability, aio.dishka). Modules that work for both sync and async stay at the top level — either directly (config, options, credentials, server, protocols, signals, settings) or as shared domain packages (interceptors → constants/utils, observability → protocols/metrics/sentry, dishka → providers).

Module Responsibility Extra
aio.GrpcApp One-object facade: config → servicers → run core
config.GrpcServerConfig Zero-dependency settings dataclass core
aio.builder.AsyncGrpcServerBuilder Fluent builder for an AsyncServer core
aio.create_async_grpc_server / aio.AsyncServer Server factory + typed wrapper core
aio.ServerLifecycleManager / aio.run_async_grpc_server Start/serve/stop with graceful shutdown core
aio.interceptors.* streaming-aware base + context, logger, metrics, tracing, sentry, exception-handler core
options / credentials / server / signals / protocols Channel options, TLS/mTLS, port binding, SIGINT/SIGTERM, seams core
settings.BaseGrpcServerSettings Pydantic config model settings
aio.health.* gRPC Health v1 servicer, orchestrator, TTL cache, pg/redis checkers health
observability.metrics.GrpcServerMetrics Prometheus metric definitions metrics
aio.observability.tracing.instrument_aio_server OpenTelemetry instrumentation tracing
observability.sentry.SentrySdkAdapter Sentry adapter for the sentry interceptor sentry
aio.dishka.* / dishka.* DI providers + DishkaAioInterceptor re-export dishka

Optional dependencies

Extra Pulls in Enables
reflection grpcio-reflection server reflection
channelz grpcio-channelz channelz debugging
settings pydantic BaseGrpcServerSettings / BaseHealthSettings
health grpcio-health-checking health servicer / orchestrator / cache
postgres sqlalchemy[asyncio] DatabaseHealthChecker
redis redis RedisHealthChecker
metrics prometheus-client GrpcServerMetrics
tracing opentelemetry-instrumentation-grpc instrument_aio_server
sentry sentry-sdk SentrySdkAdapter
dishka dishka, protobuf DI providers + DishkaAioInterceptor
all all of the above everything

Examples

Runnable, self-contained scripts in examples/ — each prints what it's doing and exits on its own:

  • minimal_server.py — the smallest real server: GrpcApp, one servicer, asyncio.run(app.run()).
  • observability_chain.py — the canonical interceptor chain (metrics → context → logger → tracing → exception handler → sentry) wired by hand.
  • custom_interceptor.py — writing your own streaming-aware interceptor with AsyncServerInterceptor.around_call.
  • health_checks.pyapp.enable_health() with a custom dependency checker, driven through the real grpc_health.v1 stubs.

Documentation

Full documentation at bedrock-python.github.io/grpc-server-kit.

License

Apache 2.0 — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

grpc_server_kit-0.1.0.tar.gz (59.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

grpc_server_kit-0.1.0-py3-none-any.whl (85.2 kB view details)

Uploaded Python 3

File details

Details for the file grpc_server_kit-0.1.0.tar.gz.

File metadata

  • Download URL: grpc_server_kit-0.1.0.tar.gz
  • Upload date:
  • Size: 59.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","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}

File hashes

Hashes for grpc_server_kit-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b54b96a5350a473bedfbc7ab1e6a7591399f55779fd4ca2451f9074a6046fc96
MD5 eea02ef3a5f0b8aec1e562ec8c0ab436
BLAKE2b-256 1638ffa27b8fb9e676b8e0408bcbdfb07d89738a9c068991c6c9d8afb2d1ce0b

See more details on using hashes here.

File details

Details for the file grpc_server_kit-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: grpc_server_kit-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 85.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","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}

File hashes

Hashes for grpc_server_kit-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 39d3151d2a5ce454f7a5b94a7dc05e73a1234e1aefa98f9f88900585eadc3a8b
MD5 b88135d33f87fe24b70f3d63d061600d
BLAKE2b-256 7172902527bde2131fef35f386f0a35aa7f59f388f909e641c61676f0f4eb116

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 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