Golang / GoLang System Architecture and Testing Interview Questions
How do you design a multi-tenant Go microservice?
Multi-tenancy means one service instance serves multiple customers (tenants) with data isolation. Three common isolation models: shared database, schema per tenant, database per tenant. The choice depends on isolation requirements, scaling needs, and cost.
// Tenant context extracted from JWT or header type TenantID string type tenantKey struct{} func withTenant(ctx context.Context, id TenantID) context.Context { return context.WithValue(ctx, tenantKey{}, id) } func tenantFromCtx(ctx context.Context) (TenantID, bool) { id, ok := ctx.Value(tenantKey{}).(TenantID) return id, ok } // Middleware: extract and validate tenant from JWT func tenantMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { claims, err := validateJWT(r.Header.Get("Authorization")) if err != nil { http.Error(w, "unauthorized", 401); return } ctx := withTenant(r.Context(), TenantID(claims.TenantID)) next.ServeHTTP(w, r.WithContext(ctx)) }) } // Shared database with tenant_id column (row-level isolation) type TenantAwareRepo struct{ db *sql.DB } func (r *TenantAwareRepo) FindUsers(ctx context.Context) ([]User, error) { tenantID, ok := tenantFromCtx(ctx) if !ok { return nil, errors.New("no tenant in context") } rows, err := r.db.QueryContext(ctx, // tenant_id filter on every query â NEVER omit this "SELECT id, name FROM users WHERE tenant_id = $1", tenantID) if err != nil { return nil, err } defer rows.Close() // ... scan rows } // Postgres Row Level Security (RLS) â DB enforces tenant isolation // ALTER TABLE users ENABLE ROW LEVEL SECURITY; // CREATE POLICY tenant_isolation ON users // USING (tenant_id = current_setting('app.tenant_id')::uuid); // SET app.tenant_id = '123e4567-...' -- per connection/transaction
More Related questions...