Service Architecture
Service Communication Pattern
All services communicate via HTTP REST APIs through API Gateway. No direct service-to-service communication.
Service Inventory
Main API (peoplehub-api)
Purpose: Core HRMS functionality
Responsibilities:
- Employee management (personal data, employment details, documents)
- Leave and attendance management
- Performance management (OKRs, reviews)
- Recruitment (jobs, candidates, interviews)
- Separation workflows
- Talent and demand management
- Settings and master data
- User and role management
Tech Stack: Node.js 22, Fastify, Drizzle ORM Database: Shared RDS PostgreSQL Endpoints: 150+ REST endpoints API Documentation: /docs endpoint (Scalar UI)
Candidate Onboarding API (candidate-api)
Purpose: Isolated onboarding workflows for security
Responsibilities:
- Candidate personal information collection
- Document uploads (pre-joining)
- Background verification workflows
- Policy acknowledgment
- E-signature integration (Digio)
- Onboarding task tracking
Tech Stack: Node.js 18, Fastify, Drizzle ORM Database: Shared RDS PostgreSQL (separate credentials) Security Isolation: Separate Lambda, separate domain, limited database access API Documentation: /docs endpoint
Integration API (integration-api)
Purpose: External system integrations and scheduled jobs
Responsibilities:
- Digio webhook handling (e-signature status updates)
- ATS integration (TalentRecruit - planned)
- Payroll system sync (planned)
- Workforce management integration (planned)
- Scheduled cron jobs (data sync, cleanup tasks)
Tech Stack: Node.js 20, Fastify, Drizzle ORM Database: Shared RDS PostgreSQL Deployment: Separate Lambda with extended timeout (for long-running sync jobs)
Notifications Service (notifications-api)
Purpose: Email notification engine
Responsibilities:
- Receive notification trigger requests
- Fetch email templates from database
- Populate templates with dynamic data
- Send emails via AWS SES
- Log notification delivery status
Tech Stack: Node.js 18, Fastify, AWS SES Database: Shared RDS PostgreSQL (read templates) Email Provider: AWS SES (Simple Email Service)
PDF Generation Service (pdf-service)
Purpose: Generate PDF documents from HTML templates
Responsibilities:
- Receive PDF generation requests
- Render HTML templates with data
- Convert to PDF using Weazy Print
- Return PDF file or upload to S3
Tech Stack: Python 3.11, Weazy Print library Why Python: Weazy Print is the best HTML-to-PDF library, only available in Python Deployment: Separate Lambda with Python runtime
Inter-Service Communication
Main API → Notifications API
Trigger: Events requiring email notifications Pattern: HTTP POST to /notifications/triggerData: Template ID, recipient, dynamic data Example: Employee leave approved → notify employee and manager
Main API → PDF Service
Trigger: Document generation requests Pattern: HTTP POST to /pdf/generateData: HTML template, data payload Example: Generate offer letter PDF for new hire
Candidate API → Notifications API
Trigger: Onboarding events Pattern: HTTP POST to /notifications/triggerExample: Candidate completes onboarding → notify HR team
Integration API → Main API
Trigger: External data sync Pattern: HTTP POST to main API endpoints Example: ATS pushes new candidate → create in recruitment module
External Systems → Integration API
Trigger: Webhook events Pattern: HTTP POST to /webhooks/{provider}Example: Digio sends e-signature completed event
Database Access Pattern
All services share the same RDS PostgreSQL instance but with different access levels:
Main API: Full read/write access to all tables Candidate API: Limited access (only onboarding-related tables) Integration API: Full read/write (for sync operations) Notifications API: Read-only access (fetch templates) PDF Service: No direct database access (receives data via API)
API Versioning
Current: v1 (implicit) Future: /v2/ prefix for breaking changes Strategy: Maintain backward compatibility, deprecate old versions gradually
Service Discovery
No service discovery needed. All services accessed via:
- Frontend → API Gateway → Lambda (AWS handles routing)
- Service-to-service → HTTP calls via base URL (environment variable)
Error Handling
Standard error response format across all services:
- HTTP status codes (400, 401, 404, 500, etc.)
- JSON error body with
messageandcode - Errors logged to CloudWatch for debugging
Authentication Between Services
Frontend → Backend: JWT in HTTP-only cookie Service → Service: API key authentication (for internal calls) External Systems → Integration API: Webhook secrets or API keys
Load Balancing
API Gateway automatically distributes requests across Lambda instances. No manual load balancer configuration needed.
Service Isolation Benefits
- Security: Candidate data isolated from main system
- Scaling: Each service scales independently based on load
- Deployment: Deploy services independently without downtime
- Fault Isolation: One service failure doesn't affect others
- Technology Choice: Use best tool for each service (Node vs Python)
Related Documentation
- System Overview - Overall architecture
- Main API - Main API details
- Candidate API - Candidate API details
- Integration Landscape - External integrations