Genèse
Ça commence par un appel client, trois semaines après un déploiement. “Le site est lent.” On regarde. Le score Lighthouse est passé de 92 à 61. Les headers de sécurité ont disparu après une mise à jour de reverse proxy. Le certificat SSL expire dans 4 jours. Tout était vert sur Uptime Robot. Personne n’a rien vu.
C’est le problème : les outils de monitoring existants répondent à une seule question, “est-ce que c’est up ?”. Mais un site peut être up et se dégrader lentement. Les performances glissent, la sécurité s’érode, la délivrabilité email se dégrade. Personne ne prévient parce que personne ne mesure.
J’ai cherché un outil qui combine le monitoring classique avec des audits de qualité. Uptime Robot fait du ping. Lighthouse fait des audits ponctuels. Datadog fait tout mais coûte une fortune et demande un bac+5 pour la configuration. Il n’existe rien qui dise simplement : “ton site répondait bien la semaine dernière, cette semaine il régresse, voici pourquoi.” C’est le créneau de Granit Golem.
Le nom vient du golem de granit. Une sentinelle patiente qui ne dort jamais. Le genre de gardien qu’on aimerait avoir eu trois semaines plus tôt.
Pourquoi ces choix
Rust pour un SaaS, c’est un choix que je dois souvent justifier. La raison, c’est que le monitoring est un domaine où les erreurs silencieuses sont les pires. Si un check oublie de vérifier un cas, si un type d’alerte est confondu avec un autre, on ne le découvre que quand un client ne reçoit pas la notification qu’il attendait. En Rust, le compilateur refuse de compiler si on oublie un cas dans un match. Un CheckId ne peut pas être passé là où on attend un AuditId. C’est plus lent à écrire, mais ça force une rigueur que je n’aurais pas eue en Node ou Go.
PostgreSQL avec Row Level Security, c’est la réponse à une question qui m’empêchait de dormir : “et si un développeur oublie le filtre WHERE org_id = ? dans une requête ?” Avec la RLS, c’est la base elle-même qui refuse de montrer les données d’une autre organisation. Le filtre est dans la base, pas dans le code. On peut oublier, PostgreSQL n’oubliera pas.
Comment ça marche
On pointe Granit Golem vers un site web ou une API. Il commence à surveiller avec des checks légers toutes les minutes : le site répond-il ? Le certificat SSL est-il valide ? Le DNS résout-il correctement ?
Les audits vont plus loin. On choisit ce qu’on veut mesurer (performance Lighthouse, headers de sécurité, délivrabilité email SPF/DKIM/DMARC…), on règle l’importance de chaque critère, et Granit Golem exécute le tout périodiquement. Le premier audit définit une baseline. Les suivants sont comparés : si quelque chose glisse au-delà d’un seuil, une alerte se déclenche. C’est la drift detection, la raison d’être du projet. Pas juste “est-ce que c’est up”, mais “est-ce que c’est aussi bien qu’avant”.
Les alertes ont un cycle de vie complet : on peut les acquitter (“je suis dessus”), les résoudre manuellement, ou laisser le système les fermer quand le problème se corrige. Des status pages publiques permettent de communiquer l’état sans que les utilisateurs aient besoin de demander.
Les cailloux dans le terreau
Décider seul
Le plus gros défi n’est pas technique. C’est de prendre toutes les décisions architecturales sans personne pour challenger. DDD ou pas ? Quel découpage ? Comment gérer le multi-tenant ? Chaque choix engage la suite. Sans revieweur, les mauvaises décisions se révèlent tard. Le constructeur du state global qui fait 469 lignes, on ne le voit pas grossir jour après jour. C’est quand on veut ajouter un nouveau service qu’on réalise que c’est devenu ingérable.
Les migrations qui s’entrechoquent
En développant sur plusieurs branches en parallèle, deux branches créent une migration avec le même timestamp. On merge, et la base refuse de démarrer. SQLx stocke un checksum de chaque migration : si on modifie une migration déjà appliquée, même une virgule, tout casse. La règle apprise dans la douleur : ne jamais toucher une migration existante, toujours en créer une nouvelle.
L’audit fantôme
Un audit qui crashe pendant la génération du rapport reste bloqué en état “Running” pour toujours. L’audit suivant reçoit un conflit. Sauf que le premier est mort. Il a fallu un job de nettoyage en arrière-plan, une détection au chargement de page, et un fix de memory leak côté frontend. Trois bugs pour un seul symptôme. Le genre de problème qui rappelle pourquoi on fait du monitoring : les choses cassent de manière inattendue.
Le monitoring du monitoring
À un moment, on se demande qui surveille le surveillant. Prometheus a été intégré pour mesurer les métriques du serveur Granit Golem lui-même. Puis on se demande si on devrait surveiller Prometheus. C’est là qu’on s’arrête et qu’on accepte qu’il y a toujours un dernier maillon non surveillé.
L’architecture
Le projet est structuré en Domain-Driven Design, avec une séparation stricte entre les règles métier et le reste. Les règles de monitoring (“un check ne peut pas tourner en même temps qu’un autre”, “le seuil d’alerte doit être supérieur au seuil d’avertissement”) vivent dans des modules qui ne savent rien de la base de données ni du framework web. On peut tester la logique métier sans démarrer PostgreSQL. C’est le genre de discipline qui semble excessive au début et qui évite les régressions trois mois plus tard.
Le frontend est un dashboard Nuxt 3 avec des graphes de tendance, des barres d’uptime et des formulaires pour configurer les audits. Rien de spectaculaire techniquement, mais il fallait que ce soit utilisable par quelqu’un qui n’est pas développeur.
Pourquoi c’est en pause
Le projet a atteint un stade fonctionnel : les checks marchent, les audits produisent des scores, la drift detection lève des alertes. Mais pour inviter de vrais utilisateurs, il manque du polish sur l’alerting (la couverture fonctionnelle est à 46%) et sur l’onboarding. Plutôt que de sortir un produit bancal, j’ai préféré mettre en pause et y revenir quand j’aurai le temps de le finir correctement.
Journal
2026-02-18
Pause. Le produit est utilisable mais pas prêt pour des vrais utilisateurs. L’alerting reste le maillon faible. Plutôt que de bâcler, on attend.
2026-01-25
Grosse journée de corrections. L’accessibilité est ajoutée sur tous les composants d’interface, une vulnérabilité dans une dépendance Rust est corrigée, et le state global monolithique est enfin découpé en quelque chose de maintenable. Le genre de journée pas glamour mais nécessaire.
2026-01-24
Sécurisation multi-tenant. Des tests vérifient qu’une organisation ne peut jamais lire les données d’une autre, même si le code applicatif oublie un filtre.
2025-12-15
Le cœur du produit prend forme. Lighthouse fonctionne comme sonde d’audit, la drift detection compare les scores à une baseline, l’interface permet de régler les poids de chaque critère. L’audit passe du concept au workflow fonctionnel.
2025-11-24
Premier commit. L’architecture complète est posée dès le jour 1. Un pari sur la rigueur dès le départ : structurer proprement même quand personne ne regarde, parce que le code d’aujourd’hui est le legacy de demain.
Stats
| Commits | 1 021 |
| Durée | 3 mois (nov 2025 → fév 2026) |
| Contributeur | solo |


