
Status Page SaaS — AWS Serverless
Projet personnel | 2025 - 2026
Projet Personnel
Vigilo est un SaaS de Status Page multi-tenant entièrement serverless, conçu et déployé sur AWS.
- Multi-tenant : chaque organisation est isolée
- Monitoring d'endpoints HTTPS toutes les 5 minutes
- Page de statut publique par slug (/status/mon-org)
- Zéro infrastructure à gérer — 100% serverless
Objectifs du Projet
Maîtriser l'écosystème AWS serverless de bout en bout, de l'infrastructure à l'application.
Livrables
- Infrastructure as Code (CloudFormation YAML)
- Backend serverless (Lambda + API GW + DynamoDB)
- Frontend Next.js déployé sur S3/CloudFront
- CI/CD GitHub Actions avec OIDC (sans secrets AWS)
Architecture AWS Serverless
3 stacks CloudFormation imbriquées — ordre de déploiement critique
| Stack | Composant | Rôle |
|---|---|---|
| DataStack | DynamoDB (single-table) | Stockage orgs, monitors, incidents avec GSIs |
| DataStack | DynamoDB (checks) | Historique health checks, TTL 30 jours |
| DataStack | Cognito User Pool | Auth multi-tenant + attribut custom:tenantId |
| ApiStack | 6 Lambda (ARM64, Node 20) | Handlers métier avec esbuild (CDK NodejsFunction) |
| ApiStack | API Gateway HTTP API | JWT Authorizer Cognito, zéro coût idle |
| ApiStack | EventBridge Scheduler | rate(5 min) → HealthCheckRunner, concurrency = 1 |
| FrontendStack | S3 + CloudFront (OAC) | Static export Next.js, cache 1 an sur assets |
| FrontendStack | SNS (runtime) | 1 topic par tenant, alertes on status change |

Multi-tenancy & Sécurité
Isolation stricte par tenant — invariant de sécurité central
JWT tenantId
- tenantId extrait uniquement du JWT Cognito
- Jamais du body ou des query params
- Attribut Cognito immutable (mutable: false)
- Assigné par trigger post-confirmation
Single-Table DynamoDB
- PK = ORG#{tenantId}
- SK = MONITOR#{id} / INCIDENT#{id}
- GSI SlugIndex pour les pages publiques
- GSI EnabledMonitorsIndex pour le health check
Ownership Check
- Chaque item DynamoDB stocke son tenantId
- Comparaison JWT vs item sur chaque appel
- Mismatch → HTTP 403 immédiat
- TransactWrite pour opérations atomiques
Health Check Runner
Lambda déclenchée toutes les 5 minutes par EventBridge
Exécution
- reservedConcurrentExecutions: 1 — pas d'overlap
- Concurrence max 10 checks en parallèle
- Promise.allSettled — erreurs non bloquantes
- SNS alerts uniquement sur changement de statut
Monitoring CloudWatch

Compétences Maîtrisées
AWS Serverless
Lambda ARM64, API GW HTTP, EventBridge, SNS — architecture event-driven sans serveur
IaC CloudFormation
3 stacks YAML imbriquées avec dépendances et outputs cross-stack
Multi-tenancy
Isolation par JWT claim (tenantId), single-table DynamoDB avec PK/SK composite
CI/CD GitHub Actions
OIDC sans credentials stockés, deploy séquentiel des stacks avec outputs dynamiques
Frontend Statique
Next.js 14 App Router, output export, Cognito SDK natif sans Amplify
Sécurité JWT
tenantId extrait uniquement du token — jamais du body. Vérification ownership sur chaque item DynamoDB