Leave and approval engine of a multi-tenant HR suite, rebuilt end to end while clients stayed live.

- Client
- Socium, HR SaaS in 20+ African countries
- Key result
- v2 rebuilt from scratch, no break for live clients
Context
Socium's HR suite runs for clients such as the Presidency of Senegal and Senegal Numerique, on Azure, Kubernetes and on premise. The Workflow product had outgrown its first version: business rules were scattered across the front end, and an Angular 15 codebase was blocking every upgrade.
What I built
As lead, I rebuilt v2 on both sides. The leave engine moved server side as the single source of truth: half days, overlapping requests, public holidays, balances and caps, eligibility and seniority rules, with a dry run mode so users see the exact outcome before submitting. On top of it: multi-step approval chains, bulk approvals, server-side exports and Redis caching on the hot read paths, plus the migration from Angular 15 to 20 (standalone components, Signals). Like the four other apps of the suite, it runs on the shared security model I put in place: tenant isolation in a common data-access layer, fail-closed guards and per-app permissions on Keycloak.
Result
A new product in production on a modern stack, delivered without a service break for tenants already live.
Architecture
Leave rules live on the server
The API is the single source of truth for balances, overlaps and eligibility, and a dry run shows the exact outcome before a request is submitted.
Tenant isolation in a shared data layer
Every query is scoped to the company by default and fails closed, which fixed the penetration test findings at the root instead of endpoint by endpoint.
Shared @socium libraries
Permissions and business rules are written once and reused by every app of the suite, so they cannot drift apart.
Permissions per app
Each app has its own Keycloak roles, with no global admin role that would open every product at once.
Stack
- Angular 20
- NestJS
- MongoDB Atlas
- Redis
- Keycloak
- Kubernetes
- Azure


