---
title: "Real-life scenario: PeopleFlow"
chapter: "16"
---

# 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.
