Vigilo Logo

Status Page SaaS — AWS Serverless

Projet personnel | 2025 - 2026

LambdaDynamoDBCloudFrontCognitoCloudFormationSNSEventBridgeNext.js

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

StackComposantRôle
DataStackDynamoDB (single-table)Stockage orgs, monitors, incidents avec GSIs
DataStackDynamoDB (checks)Historique health checks, TTL 30 jours
DataStackCognito User PoolAuth multi-tenant + attribut custom:tenantId
ApiStack6 Lambda (ARM64, Node 20)Handlers métier avec esbuild (CDK NodejsFunction)
ApiStackAPI Gateway HTTP APIJWT Authorizer Cognito, zéro coût idle
ApiStackEventBridge Schedulerrate(5 min) → HealthCheckRunner, concurrency = 1
FrontendStackS3 + CloudFront (OAC)Static export Next.js, cache 1 an sur assets
FrontendStackSNS (runtime)1 topic par tenant, alertes on status change
Architecture Vigilo

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

EventBridgeGSI ScanPromise.allSettledSNS Publish
  • 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

CloudWatch Logs Vigilo

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

AWS LambdaDynamoDBCloudFormationCognitoCloudFrontS3SNSEventBridgeNext.jsTypeScriptGitHub Actions