01 - Product Overview (Health Module)
StudyLyon - multi-tenant ERP / School Management API. This package designs the Health module client (Flutter, forward-looking spec) against the implemented NestJS backend. All endpoints, indicator keys, wire contracts, rate limits and auth posture are derived directly from
src/modules/health/**,src/app/app.module.ts,src/common/guards/rate-limit.constants.ts,src/common/interceptors/response-envelope.interceptor.ts,src/common/filters/http-exception.filter.ts,src/modules/rbac/permissions.constants.tsanddocs/IMPLEMENTATION_PLAN.md. No feature is invented - anything not present in source is flagged(planned)/(proposed)/(forward-looking).
Heads-up: per the PRD, the mobile client is out of Phase 1 scope
(PRODUCT_REQUIREMENTS_DOCUMENT.md:144 - "Native mobile apps (web-first)");
this package is the forward-looking spec the client will be built against later.
The health endpoint itself is a machine-to-machine surface first: it exists for
load balancers, orchestrators and uptime probes, and only secondarily for humans.
1. Purpose
The health module exposes a single Terminus-powered check endpoint that reports the reachability of the API's runtime dependencies in one round-trip:
GET /api/v1/health- combined check of four indicators (health.controller.ts:27-37): MongoDB ping, Redis PING, storage provider reachability probe, and BullMQ queue accessibility with pending-job counts.- Status model - Terminus
HealthCheckResultshape:status(ok|error),info,error,details; individual dependencies reportup/down(health.controller.spec.ts:21-36). - HTTP semantics - 200 when every dependency is up; 503
(ServiceUnavailableException raised by
@HealthCheck) when any is down. - Public by design -
@Public()bypasses the JWT/RBAC global guards (health.controller.ts:15,app.module.ts:129-131); rate-limited to 30 req/min on thepublictier (health.controller.ts:16,rate-limit.constants.ts:4,IMPLEMENTATION_PLAN.md:48).
| Responsibility | Source |
|---|---|
| Terminus registration | health.module.ts:8-17 (imports TerminusModule, declares 3 custom indicators) |
| Combined check endpoint | health.controller.ts:27-37 |
| MongoDB indicator | Terminus MongooseHealthIndicator.pingCheck('mongodb'), health.controller.ts:32 |
| Redis indicator (PING) | redis-health.indicator.ts:12-23 |
| Storage indicator (provider probe) | storage-health.indicator.ts:16-26, storage-provider.ts:21-27 |
| BullMQ indicator (4 queues, job counts) | bullmq-health.indicator.ts:19-37, queue.constants.ts:2,5,14, dlq.constants.ts:1 |
| Module wiring | app.module.ts:87 |
| Public tier rate limit | rate-limit.constants.ts:4, IMPLEMENTATION_PLAN.md:48 |
2. Business goals
| Goal | Measure |
|---|---|
| One-probe dependency visibility | all 4 indicators answered in a single request (health.controller.ts:31-36) |
| Orchestrator-ready signals | 200 on status: 'ok', 503 on any down (Terminus @HealthCheck behavior) |
| No auth overhead for probes | @Public() bypass (health.controller.ts:15); load balancers need no tokens |
| Abuse containment | 30 req/min sliding-window, Redis-backed (rate-limit.constants.ts:4) |
| Partial-failure detail | error + details keys distinguish which dependency failed while others stay up (health.controller.spec.ts:29-35) |
3. User goals
- Platform / DevOps engineer: one curl-able endpoint that says whether the API, DB, Redis, object storage and background queues are reachable, and which one is not when something is.
- Support engineer: a fast "is it us or is it them?" signal before opening tickets.
- School admin (forward-looking): a visual "App Health" screen in the admin
surface that mirrors the endpoint as status cards, with the option to re-check
manually -
(proposed)throughout this package.
4. Scope
4.1 In scope (implemented backend)
Single combined endpoint GET /api/v1/health (and /api/v2/health, both
versions registered - health.controller.ts:28) with four indicators:
mongodb, redis, storage, bullmq (health.controller.ts:31-36). Terminus
HealthCheckResult response envelope (200/503). @Public() + public rate
tier (30 req/min). Custom indicators carry extra payload: Redis reports its
ping value (redis-health.indicator.ts:16), BullMQ reports per-queue
pendingJobs counts (bullmq-health.indicator.ts:30).
4.2 Planned (not in source)
- Liveness/readiness split -
GET /api/v1/health/readyandGET /api/v1/health/liveappear indocs/user-flows/END_TO_END_USER_FLOWS.md:738-740but no such routes exist inhealth.controller.tstoday; the single combined check covers both concerns - marked(planned)throughout. - Disk and memory indicators - Terminus ships
DiskHealthIndicator/MemoryHealthIndicatorbut neither is wired; onlymongodb,redis,storage,bullmqare checked (health.controller.ts:31-36). - Uptime / version fields - the response carries no uptime, process
version, or build hash;
HealthCheckResultis returned verbatim (health.controller.ts:30-37).
4.3 Forward-looking (client roadmap)
"App Health" admin screen (status cards for API, DB, Redis, Queues, Storage;
last-check time; manual retry) - (proposed) in 05/06. Per PRD the native
client itself is post-Phase 1 (PRODUCT_REQUIREMENTS_DOCUMENT.md:144).
4.4 Proposed (analytics)
Analytics events on screens (health.*.*) per 00-shared/10 §8 - (proposed).
5. Non-goals (this version)
- Authenticated health variants - no
health.*permission exists inpermissions.constants.ts:1-97(verified: zero matches for "health"); the endpoint is public and rate-limited only. A guarded admin variant is(proposed)for the future screen. - Per-tenant health - no
tenantIdscoping; health is a global infrastructure concern (AGENTS.mdtenancy conventions do not apply). - Diagnostics depth - no latency metrics, no per-queue detail beyond
summed
pendingJobs(bullmq-health.indicator.ts:27-30), no DB query timing. - Historical availability - endpoint is stateless; no uptime history, no incident log, no alerting (alerting out of scope of this module).
- Load-shedding - the check itself has no timeout budget; a hanging
dependency hangs the probe until the global
RequestTimeoutMiddleware(app.module.ts:141) or client-side timeout fires.