Skip to main content

Architecture Overview

System diagram​

Backend architecture​

All backend services are Spring Boot 4.x applications on Java 17, packaged as Docker images. Each service owns its database schema (database-per-service pattern) and validates JWTs independently.

Service responsibilities​

ServicePrimary roleSync HTTPAsync (Kafka)
api-gatewayRoute proxy, CORSReceives all browser traffic—
auth-serviceCredentials, JWT issuance, refresh sessions/auth/**—
user-serviceUser profiles/api/user/**—
book-serviceCatalog CRUD, cover upload/api/books/**, etc.—
order-serviceOrder read/cancel/api/orders/**Consumes payment-success; produces order-created
payment-serviceStripe checkout/webhooks/api/payments/**Produces payment-success, payment-failed
notification-serviceEmail + SMSNone (Kafka-only)Consumes order-created
analytics-serviceAdmin dashboards/analytics/**Consumes order-created, payment-failed, payment-completed

REST communication (OpenFeign)​

ClientCallerTargetAuth
UserServiceClientauth-serviceuser-service /api/user/createX-Internal-Api-Key header
BookServiceClientorder-servicebook-service /api/books/batchForwards caller JWT
UserServiceClientorder-serviceuser-service profile endpointsForwards caller JWT

payment-service uses Spring RestClient (not Feign) to call book-service and user-service during checkout.

Event-driven communication (Kafka)​

Kafka runs in KRaft mode (Apache Kafka 3.9.1) — locally via Docker Compose, in production as a Kubernetes StatefulSet in the bookstore namespace.

Authentication flow

  1. User registers or logs in via POST /auth/register or POST /auth/login.
  2. auth-service validates credentials, calls user-service to create a profile on registration, and returns a short-lived JWT access token plus a refresh token stored as a device session.
  3. Frontend stores tokens and sends Authorization: Bearer <token> on subsequent requests.
  4. Each secured service validates the JWT with a shared JWT_SECRET.
  5. Token refresh: POST /auth/refresh rotates the refresh token.

Payment flow (Stripe)

Notification flow

  1. order-service publishes order-created after building an order from payment-success.
  2. notification-service consumes the event.
  3. It sends email via Mailtrap SMTP and SMS via Twilio (when configured).
  4. Notification delivery state is persisted in bookstore_notification_db.

Analytics flow

  1. analytics-service consumes order-created and payment-failed events.
  2. Events are deduplicated via a processed_events table.
  3. Aggregates power admin dashboard APIs under /analytics/** (ADMIN role required).
  4. See the known topic mismatch for successful payment analytics.

Database strategy​

The project follows a database-per-service pattern:

ServiceDatabase
auth-servicebookstore_auth_db
user-servicebookstore_user_db
book-servicebookstore_books_db
order-servicebookstore_order_db
notification-servicebookstore_notification_db
payment-servicebookstore_payment_db
analytics-servicebookstore_analytics_db

Locally, a single MySQL instance hosts all databases (initialized by docker/mysql/init.sql). In production, services connect to Amazon RDS MySQL inside the VPC.

Security model​

  • JWT bearer tokens are issued by auth-service
  • Refresh tokens are stored in auth-service as device sessions with rotation
  • Most services require authentication for all routes, then narrow access with @PreAuthorize
  • Admin-only paths are enforced in controllers and security config
  • Internal service-to-service calls from auth-service to user-service use X-Internal-Api-Key

Production deployment pipeline​

Production deployment uses GitOps. Kubernetes manifests and Terraform live in the bookstore-infra repository (not in this codebase).

Details:

What exists in each repository​

Assetbookstore (this repo)bookstore-infra
Application source codeYes—
Docker Compose (local)Yes—
Per-service DockerfilesYes—
GitHub Actions CI workflowYes—
Kubernetes manifests—Yes (k8s/)
Argo CD Applications—Yes
Terraform (VPC, EKS, RDS, ECR, S3, OIDC)—Yes
Monitoring stack (Prometheus, Grafana)Actuator metrics onlyYes (k8s/monitoring/)