Real-life scenario: PeopleFlow
PeopleFlow is a global hiring and employee platform. Customers use its web and mobile APIs. It integrates with Salesforce for sales/customer context, Workday for employee records, and SAP for finance and purchase approvals.
Requirements
- 99.95% candidate application availability.
- Tenfold campaign traffic within ten minutes.
- No duplicate hires, invoices, or onboarding tasks.
- Workday and SAP may be slow or unavailable for hours.
- Five-minute RPO and one-hour RTO for hiring workflows.
- Independent domain teams with consistent security and observability.
Architecture
Build a Spring Boot application organized as modules: Candidate, Job, Application, Offer, Onboarding, and Integration. Start as a modular monolith to keep transactions and delivery simple. Verify module boundaries with Spring Modulith. Extract only a proven independent capability later.
Spring MVC controllers accept DTOs, apply Bean Validation, and call application services. Business rules live in domain modules. Spring Data JPA persists aggregates to PostgreSQL. Transactions are short.
When an offer is accepted, the application commits the state and an outbox record together. A publisher sends durable events to Kafka. Idempotent adapters update Workday, SAP, and Salesforce with timeouts, backoff, rate limits, dead letters, and reconciliation. A vendor outage never holds the user HTTP request open.
Use Spring Security as an OAuth 2.0 resource server. Validate issuer and audience, then authorize tenant and business ownership in services. Secrets come from a managed store. The application runs as a non-root container with immutable artifacts and database migrations designed with expand/contract.
Actuator exposes controlled health and Prometheus metrics. OpenTelemetry traces HTTP, SQL, Kafka, and vendor calls. SLO alerts focus on successful applications, offer acceptance, integration age, and error-budget burn.
Failure example: Workday is down
Offer acceptance still succeeds after the local durable commit. The Workday event waits in the broker. Consumer concurrency is capped. Queue age alerts operators. When Workday returns, idempotent processing drains the backlog and reconciliation checks missed records.
Prove it
Test module boundaries, transaction rollback, authorization, schema contracts, duplicate messages, vendor timeouts, campaign load, instance termination, database restore, and a one-hour regional recovery.
Decision record
Chosen: modular monolith, MVC, PostgreSQL, outbox plus Kafka, OAuth resource server, controlled Actuator, and evidence-based extraction.
Rejected: one microservice per table, synchronous vendor calls in user requests, shared admin tokens, and unbounded retries.