Skip to content

IQKV/microservices-platform

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

783 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

🚀 IQ Key Value Microservices Platform

Spring Boot microservices platform demonstrating modern architecture patterns, security best practices, and operational excellence for building scalable distributed systems.

Table of Contents

Business Purpose

A microservices ecosystem that provides:

  • Identity & Access Management - Centralized authentication with RS256 JWT tokens, multi-tenant user lifecycle, email verification, invitation flows, and role-based access control
  • API Gateway - Reactive entry point with JWT validation, header sanitization, tenant context injection, and platform mode consistency enforcement
  • Billing & Payments - Stripe-backed subscription management, plan catalog, webhook processing, and event-driven billing notifications
  • Extensible Platform - Foundation for adding new microservices with standardized security, observability, and integration patterns

This platform serves as a reference implementation for organizations building microservices architectures, showcasing production-ready patterns for authentication, API management, and business domain services.

Platform Services

Centralized authentication and identity management hub.

Core Capabilities:

  • JWT-based authentication with RS256 (JwtTokenGenerator with RSA PEM keys)
  • User registration via SignupStrategyMULTI_TENANT creates a new tenant + grants TENANT_OWNER; SINGLE_TENANT joins the default tenant with MEMBER
  • Email verification with 64-char hex one-time tokens, 24h expiry, rate-limited resend (3/hour)
  • Password reset with 32-byte hex tokens, configurable TTL, enumeration-safe responses
  • Tenant invitation flow — send, preview, accept (existing or new user), revoke
  • Two-layer token revocation: JTI denylist (per-signout) + last_global_signout_at (signout-all)
  • Account lockout after configurable failed attempts with sliding window
  • Schema-per-tenant PostgreSQL isolation (t_{tenantKey}) provisioned via Liquibase on tenant.created events
  • JWKS endpoint (/.well-known/jwks.json) for public key distribution
  • Tenant lifecycle management: PROVISIONING → ACTIVE → SUSPENDED/DELETED with event publishing
  • Admin user management with paginated listing and partial updates

Key Patterns:

  • JwtAuthenticationFilter runs before Spring Security — checks JTI denylist and last_global_signout_at on every request
  • MyBatisSchemaInterceptor sets PostgreSQL search_path to t_{tenantKey}, public per request
  • TenantLiquibaseRunner provisions tenant schemas asynchronously via RabbitMQ (tenant.createdtenant.provisioned)
  • StuckTenantReaperJob marks tenants stuck in PROVISIONING as PROVISIONING_FAILED every 5 minutes
  • SubscriptionEventConsumer suspends tenants on subscription.cancelled events from Billing
  • PlatformModeInfoContributor exposes platform.rollout-mode via /actuator/info for Gateway validation
  • Hourly ShedLock-protected cleanup jobs for expired tokens, verification tokens, and invitations
  • Micrometer counters for auth.success, auth.failure (with tenant and reason tags), and tenant.created

Reactive API gateway providing the single external entry point for all services.

Core Capabilities:

  • JWT validation via JWKS endpoint (Spring Security OAuth2 Resource Server, reactive)
  • Routes: /.well-known/** and /api/v1/iam/** → IAM; /api/v1/billing/** → Billing
  • Global CORS configuration with configurable allowed origins
  • Platform mode consistency enforcement — polls IAM /actuator/info every 60s; returns 503 on mismatch
  • Correlation ID generation and propagation (X-Correlation-ID)
  • Security response headers on all responses

Key Patterns:

  • HeaderSanitizationFilter (order -190) strips all X-User-*, X-Tenant-ID, X-Organization-ID headers from incoming requests before JWT processing — prevents identity spoofing
  • JwtContextPropagationFilter (order -100) reads validated JWT from ReactiveSecurityContextHolder and injects X-User-ID, X-Username, X-User-Email, X-Tenant-ID, X-User-Authorities for downstream services
  • TenantContextFilter (order -50) — MULTI_TENANT: passes X-Tenant-ID from JWT; SINGLE_TENANT: injects defaultTenantKey when header is absent
  • ResponseTransformationFilter (order MIN_VALUE+1) adds X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy to all responses
  • PlatformModeGuardFilter validates rollout mode consistency with IAM at startup and on a 60s schedule; sets readiness to REFUSING_TRAFFIC on mismatch
  • Type-safe configuration with @ConfigurationProperties records (GatewayProperties, GatewayConfigurationProperties, PlatformConfigurationProperties)

Stripe-backed subscription and billing management service.

Core Capabilities:

  • Plan catalog with MONTHLY/ANNUAL billing periods, minor-unit pricing, feature sets (JSON), and TENANT/USER scope
  • Subscription management with Stripe-synced status (active, trialing, past_due, canceled, unpaid)
  • Stripe webhook processing with idempotency via webhook_log table — handles customer.subscription.* and invoice.* events
  • Billing settings per tenant: Stripe customer ID, billing email, company name, address, tax ID
  • User billing settings for SINGLE_TENANT mode: per-user Stripe customer creation
  • Entitlement evaluation: resolves active subscription + plan feature set for a subject (tenant or user)
  • Event-driven bootstrap: TenantEventConsumer creates Stripe customer on tenant.created; UserEventConsumer cleans up profileOwnerId on user removal
  • Email notifications: subscription activated, subscription cancelled, invoice paid, payment failed
  • Scheduled trial and overdue notifications (daily at 9AM and 10AM UTC via ShedLock)

Key Patterns:

  • SubscriptionSubjectResolver strategy — MULTI_TENANT: subject is TENANT/tenantKey; SINGLE_TENANT: subject is USER/userId
  • PlanEligibilityPolicyImpl validates plan scope matches subject type before subscription creation
  • WebhookProcessingService idempotency: checks webhook_log by externalEventId before processing; status lifecycle RECEIVED → PROCESSED/FAILED
  • BillingContactResolver fallback chain: ownerEmail from event → DEFAULT_BILLING_EMAIL env var → null (Stripe allows no email)
  • TrialNotificationService finds trials ending in 2–3 days and past_due subscriptions daily
  • TenantExtractionFilter resolves tenant from X-Tenant-ID header (injected by Gateway) with context validation
  • PaymentGatewayClient wraps Stripe SDK; initialized with secretKey at construction

Architecture Overview

Microservices Architecture

┌─────────────┐
│   Clients   │
│ (Web/Mobile)│
└──────┬──────┘
       │ :80
       ▼
┌──────────────────────────────────────────┐
│         Gateway Service (:8080)          │
│  • JWT Validation (JWKS from IAM)        │
│  • Header Sanitization + Propagation     │
│  • Tenant Context Injection              │
│  • Platform Mode Guard                   │
│  • Security Response Headers             │
└──────┬──────────────────┬────────────────┘
       │                  │
       ▼                  ▼
┌─────────────────┐  ┌──────────────────────┐
│   IAM Service   │  │   Billing Service    │
│  • Auth / JWT   │  │  • Subscriptions     │
│  • Users        │  │  • Plan Catalog      │
│  • Tenants      │  │  • Stripe Webhooks   │
│  • Invitations  │  │  • Billing Settings  │
│  • JWKS         │  │  • Entitlements      │
└────────┬────────┘  └──────────┬───────────┘
         │                      │
         ▼                      ▼
┌─────────────────┐  ┌──────────────────────┐
│  PostgreSQL IAM │  │  PostgreSQL Billing  │
│  (schema/tenant)│  │                      │
└─────────────────┘  └──────────────────────┘

Shared Infrastructure
┌──────────────────┐  ┌──────────────────────┐  ┌──────────────────────┐
│     RabbitMQ     │  │       MailHog        │  │    Observability     │
│  iqkv.events     │  │  (local SMTP)        │  │  Prometheus/Grafana  │
│  topic exchange  │  │                      │  │  Loki / Promtail     │
└──────────────────┘  └──────────────────────┘  └──────────────────────┘

Technology Stack

  • Runtime: Java 25 with modern features (records, var, text blocks, pattern matching, switch expressions)
  • Framework: Spring Boot 4.x, Spring Cloud Gateway (WebFlux/reactive)
  • Database: PostgreSQL 17 with Liquibase migrations, MyBatis, schema-per-tenant isolation
  • Messaging: RabbitMQ topic exchange with dead-letter queues and 24h message TTL
  • Security: JWT with RS256 (JJWT), Spring Security OAuth2 Resource Server, BCrypt strength 12
  • Payments: Stripe Java SDK for customer and subscription management
  • Observability: Prometheus (Micrometer), Grafana, Loki, Promtail, structured JSON logging (Logstash Logback Encoder)
  • Distributed Locking: ShedLock with JDBC provider for scheduled jobs
  • API Documentation: SpringDoc OpenAPI with Swagger UI (webmvc + webflux variants)
  • Testing: JUnit 5, Testcontainers, ArchUnit, H2
  • Containerization: Docker with multi-stage builds, Docker Compose for local development

Key Features

Security & Authentication

  • RS256 JWT authentication issued by IAM, validated at Gateway via JWKS
  • Two-layer token revocation: JTI denylist (per-signout) + last_global_signout_at (signout-all)
  • JwtAuthenticationFilter checks both revocation layers before Spring Security processes the request
  • HeaderSanitizationFilter strips all user/tenant identity headers from client requests before JWT propagation — prevents spoofing
  • JWT claims propagated downstream as X-User-ID, X-Username, X-User-Email, X-Tenant-ID, X-User-Authorities
  • Role-based access control with @PreAuthorize and @EnableMethodSecurity
  • Account lockout after configurable failed login attempts with sliding window
  • Email verification with one-time tokens and rate-limited resend
  • Password reset with enumeration-safe responses and session invalidation on completion
  • Tenant invitation flow with authority assignment and support for both existing and new users

Multi-Tenancy

  • MULTI_TENANT mode: each signup creates a new tenant; subscriptions scoped per tenant
  • SINGLE_TENANT mode: all users join a default tenant; subscriptions scoped per user
  • Strategy pattern (SignupStrategy, SubscriptionSubjectResolver) selects behavior via @ConditionalOnProperty
  • All three services validate rollout mode at startup; Gateway additionally polls IAM every 60s and blocks traffic on mismatch
  • Schema-per-tenant PostgreSQL isolation in IAM — MyBatisSchemaInterceptor sets search_path per request
  • Tenant provisioning via async RabbitMQ flow: tenant.created → Liquibase migrations → tenant.provisioned

Event-Driven Integration

  • RabbitMQ topic exchange iqkv.events with dead-letter exchange and 24h TTL on all queues
  • IAM publishes: tenant.created/provisioned/provisioning_failed/suspended/deleted, user.created/deleted/removed/invited, notification.iam.email
  • Billing consumes tenant.created to bootstrap Stripe customer and billing settings
  • Billing publishes: subscription.created/cancelled, invoice.paid, payment.failed, notification.billing.email
  • IAM consumes subscription.cancelled to suspend the corresponding tenant
  • ShedLock prevents duplicate scheduled job execution across clustered deployments

Operational Excellence

  • Structured JSON logging (Logstash Logback Encoder) for all services
  • Correlation ID generated at Gateway, propagated through all downstream services and logs
  • Prometheus metrics with Micrometer — auth counters with tenant/reason tags, auth duration timer
  • Grafana dashboards provisioned from docker/grafana/provisioning
  • Health checks on management port 8081 with readiness/liveness probes
  • Graceful shutdown configured on all services
  • Environment-specific profiles: local, sit, uat, prd

Developer Experience

  • OpenAPI documentation with Swagger UI — Gateway aggregates specs from IAM and Billing
  • Docker Compose for local development with MailHog for email testing
  • Consistent RFC 7807 error responses across all services
  • Architecture validation with ArchUnit
  • Integration tests with Testcontainers (PostgreSQL, RabbitMQ)
  • Demo data Liquibase context for local development

Architecture Patterns

Cross-Cutting Patterns

  • Database Per Service — IAM and Billing each own a dedicated PostgreSQL instance
  • API Gateway — single external entry point; downstream services not directly exposed
  • Event-Driven Choreography — services react to domain events via RabbitMQ without direct coupling
  • Distributed Locking — ShedLock with JDBC provider ensures scheduled jobs run once across replicas
  • Correlation ID Tracking — generated at Gateway, propagated through all services and logs
  • Platform Mode Guard — all three services enforce rollout mode consistency at startup

Communication Patterns

  • Synchronous REST APIs with proper HTTP semantics and RFC 7807 error responses
  • JWT-based user context propagation via headers (X-User-ID, X-Tenant-ID, X-User-Authorities)
  • Asynchronous event publishing via RabbitMQ topic exchange with dead-letter queues
  • Gateway aggregates downstream OpenAPI specs for unified Swagger UI
  • Webhook ingestion from Stripe with signature verification and idempotency

Getting Started

Prerequisites

  • Java 25+
  • Docker and Docker Compose

Full Platform (all services)

# Start the entire platform from the repository root
docker compose up

# Platform entry point
# http://localhost:80  →  Gateway Service
# http://localhost:8888/dashboard/  →  Traefik Dashboard

Individual Service Development

Each service can be run independently with its own Docker Compose:

# IAM Service with PostgreSQL, RabbitMQ, MailHog
cd foundation-iam-service
docker compose up

# Billing Service with PostgreSQL, RabbitMQ, MailHog
cd foundation-billing-service
docker compose up

# Gateway Service (expects IAM running separately)
cd foundation-gateway-service
docker compose up

API Documentation

Once services are running, access Swagger UI:

  • Gateway (aggregated): http://localhost:80/swagger-ui.html
  • IAM Service (direct): http://localhost:8080/swagger-ui.html
  • Billing Service (direct): http://localhost:8080/swagger-ui.html

Monitoring

Access observability tools via Traefik virtual hosts (add to /etc/hosts or use a local DNS):

  • Grafana: http://grafana.localhost
  • Prometheus: http://prometheus.localhost
  • RabbitMQ Management: http://rabbitmq.localhost
  • MailHog: http://mailhog.localhost
  • Health checks: http://{service}:8081/actuator/health

Learning Objectives

This platform demonstrates:

Microservices Architecture

  • Service decomposition and bounded contexts
  • Database per service pattern
  • API gateway as single entry point
  • Event-driven choreography with RabbitMQ
  • Async tenant provisioning with status lifecycle and failure recovery

Security Implementation

  • RS256 JWT issuance and validation across services
  • Two-layer token revocation (JTI denylist + global signout timestamp)
  • Header sanitization to prevent identity spoofing at the gateway
  • JWT claim propagation to downstream services
  • Schema-per-tenant data isolation with MyBatis interceptor
  • Enumeration-safe password reset and email verification flows

Multi-Tenancy

  • Strategy pattern for MULTI_TENANT vs SINGLE_TENANT behavior
  • Conditional Spring beans with @ConditionalOnProperty
  • Cross-service rollout mode consistency enforcement
  • Tenant lifecycle with async provisioning and failure recovery

Operational Patterns

  • Structured JSON logging with correlation ID propagation
  • Prometheus metrics with business-relevant tags
  • ShedLock for distributed scheduled job coordination
  • Dead-letter queues for messaging fault tolerance
  • Readiness probe integration with platform mode guard

Modern Java Development

  • Java 25 features (records, var, text blocks, pattern matching, switch expressions)
  • Immutable DTOs with records and @ConfigurationProperties records
  • Reactive programming with WebFlux and Project Reactor (Gateway)
  • Spring Boot 4.x best practices with type-safe configuration
  • MyBatis with XML mappers and custom type handlers
  • Clean package-by-feature structure with clear layer separation

Adapting for Your Domain

This platform provides reusable patterns for:

Authentication & Authorization

  • Multi-tenant SaaS applications with per-tenant schema isolation
  • Single-tenant applications with per-user billing
  • Partner and employee portals with invitation-based onboarding
  • Any system requiring centralized JWT issuance with downstream validation

API Gateway Patterns

  • Reactive entry point with JWT validation and context propagation
  • Header sanitization before forwarding to internal services
  • Platform-wide configuration consistency enforcement
  • Aggregated API documentation across multiple services

Billing & Subscriptions

  • SaaS subscription management with Stripe
  • Plan catalogs with scope-based eligibility (tenant vs user)
  • Webhook-driven subscription lifecycle with idempotent processing
  • Event-driven billing notifications and trial management

The patterns demonstrated here apply to any organization building microservices architectures requiring centralized authentication, API management, and scalable domain services.


Use this as a foundation for building production-ready microservices with modern Spring Boot, demonstrating security, observability, and operational excellence patterns that scale.

About

Spring Boot microservices platform demonstrating modern architecture patterns, security best practices, and operational excellence for building scalable distributed systems.

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Contributors