apadana

module
v0.0.5-beta Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 23, 2026 License: MIT

README

apadana: Multi-Tenant SDK for Go

Test Lint Security Go Version License Go Report Card GoDoc

A Go SDK providing building blocks for multi-tenant applications. Handles tenant identification, context propagation, per-tenant configuration, metrics, logging, and instrumentation across common infrastructure.

Features

  • Tenant Isolation — Extract, propagate, and inject tenant IDs across HTTP, gRPC, Kafka, NATS, and RabbitMQ
  • SaaS-Ready — Per-tenant configuration, singletons, timezones, and rate limiting out of the box
  • Context Propagation — Thread-safe tenant context with context.Context integration
  • Multi-Tenant Middleware — HTTP (standard lib & Echo) middlewares for header, query, subdomain, cookie, and JWT extraction
  • Tenant Resolver Chain — Chain-of-responsibility pattern for flexible tenant resolution
  • Per-Tenant Infrastructure — Kafka/NATS/RabbitMQ header injection
  • Observability — OpenTelemetry span processor, structured logging with log/slog
  • Generic SDK Managers — Type-safe ConfigMgr[T] and SDKMgr[T,C] for any multi-tenant resource
  • YAML Config Expansion — Merge default and per-tenant configs with ${tenant} placeholder replacement
  • gRPC Support — Unary and stream interceptors for tenant metadata propagation

Installation

go get github.com/PapaDanielVi/apadana

Quick Start

package main

import (
	"log/slog"
	"net/http"

	"github.com/PapaDanielVi/apadana/pkg/context"
	"github.com/PapaDanielVi/apadana/pkg/middleware"
)

func main() {
	handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		tenantID, _ := context.TenantIDFromContext(r.Context())
		slog.Info("request", "tenant", tenantID)
		w.Write([]byte("hello " + tenantID))
	})

	mw := middleware.TenantMiddleware(middleware.FromHeader("X-Tenant-Id"))(handler)
	http.ListenAndServe(":8080", mw)
}

See examples/basic-http for a complete runnable example.

Architecture

┌─────────────┐     ┌──────────────┐     ┌─────────────────┐
│ HTTP/gRPC   │────▶│  Middleware  │────▶│ context.Context │
│ Request     │     │  /Resolver   │     │ (tenant ID)     │
└─────────────┘     └──────────────┘     └────────┬────────┘
                                                   │
                    ┌──────────────────────────────┼──────────────┐
                    │              │               │              │
              ┌─────▼─────┐ ┌──────▼──────┐ ┌─────▼─────┐ ┌─────▼─────┐
              │ ConfigMgr │ │  SDKMgr     │ │  Logger   │ │  OTel     │
              │ [T]       │ │  [S,C]      │ │  (slog)   │ │  SpanProc │
              └───────────┘ └─────────────┘ └───────────┘ └───────────┘
                    │              │               │              │
              ┌─────▼──────────────▼───────────────▼──────────────▼─────┐
              │              Kafka / NATS / RabbitMQ                    │
              │              (X-Tenant-Id header injection)             │
              └────────────────────────────────────────────────────────┘

Packages

Package Description Key Functions / Types
pkg/context Tenant ID in context.Context WithTenantID, TenantIDFromContext, HasTenantID
pkg/mt Generic multi-tenant tools SetDefTenant, ExtractTID, InjectTID, ConfigMgr[T], SDKMgr[T,C], CloneCtx, ExpandConfigReader
pkg/middleware HTTP middlewares (std, Echo) TenantMiddleware, FromHeader, FromQuery, FromSubdomain, TenantEchoMiddleware, PrometheusEchoMiddleware
pkg/resolver Tenant resolver chain Chain, FromHeader, FromQuery, FromSubdomain, FromCookie, FromJWTClaim, Tenant, Registry
pkg/grpc gRPC interceptors UnaryServerInterceptor, StreamServerInterceptor, UnaryClientInterceptor, StreamClientInterceptor
pkg/timezone Per-tenant timezone settings Set, Now — returns time in tenant's timezone
pkg/logger Logger with tenant_id field New(ctx) — wraps log/slog with tenant ID
pkg/otel OpenTelemetry span processor NewTenantIDProcessor() — adds tenant_id to spans
pkg/rabbitmq RabbitMQ with X-Tenant-Id header Publisher, Consumer
pkg/kafka Kafka with X-Tenant-Id header Producer, Consumer
pkg/nats NATS with X-Tenant-Id header Publisher, Subscriber
pkg/httpclient HTTP client with tenant header injection Do(ctx, req) — auto-injects X-Tenant-Id
pkg/burst Per-tenant token bucket rate limiter New(rate, burst), Allow(ctx)

Design Decisions

See docs/adr for architecture decision records:

License

MIT

Directories

Path Synopsis
examples
basic-http command
Command basic-http demonstrates a minimal multi-tenant HTTP server.
Command basic-http demonstrates a minimal multi-tenant HTTP server.
pkg
burst
Package burst provides per-tenant burst rate limiting.
Package burst provides per-tenant burst rate limiting.
context
Package tctx provides context utilities for multi-tenant applications.
Package tctx provides context utilities for multi-tenant applications.
grpc
Package grpc provides multi-tenant gRPC interceptors.
Package grpc provides multi-tenant gRPC interceptors.
httpclient
Package httpclient provides an HTTP client that injects tenant ID headers.
Package httpclient provides an HTTP client that injects tenant ID headers.
kafka
Package kafka provides multi-tenant Kafka tools.
Package kafka provides multi-tenant Kafka tools.
logger
Package logger provides a slog wrapper that includes tenant ID in log output.
Package logger provides a slog wrapper that includes tenant ID in log output.
middleware
Package middleware provides HTTP middleware for tenant identification.
Package middleware provides HTTP middleware for tenant identification.
mt
Package mt provides generic multi-tenant tools.
Package mt provides generic multi-tenant tools.
nats
Package nats provides multi-tenant NATS tools.
Package nats provides multi-tenant NATS tools.
otel
Package otel provides OpenTelemetry instrumentation for multi-tenant apps.
Package otel provides OpenTelemetry instrumentation for multi-tenant apps.
rabbitmq
Package rabbitmq provides multi-tenant RabbitMQ tools.
Package rabbitmq provides multi-tenant RabbitMQ tools.
resolver
Package resolver provides tenant resolution via chain-of-responsibility.
Package resolver provides tenant resolution via chain-of-responsibility.
timezone
Package timezone provides per-tenant timezone management.
Package timezone provides per-tenant timezone management.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL