Comment nous avons préparé un site mutualisé à la maintenance avec Cloudflare Workers
Réponse rapide
Un site PHP surtout statique peut rester utile pendant une panne planifiée sans déplacer le compte actif. Devant KeyboardTester.click, le Worker laisse passer toute réponse saine à l’identique et sert une copie statique lors d’erreurs réseau ou serveur ciblées. Dès que l’origine répond normalement, le trafic y revient automatiquement. C’est une continuité pragmatique, pas du zéro interruption universel : formulaires, e-mail, IA côté serveur et enregistrements restent dépendants de l’hébergeur.
L’avis annonçait une fenêtre de six heures sans durée de panne précise. Attendre un e-mail créait un délai manuel ; basculer le DNS vers une seule page aurait conservé le message, pas les contenus et outils attendus.
Voici l’architecture réellement déployée : échange HostArmada, logique du Worker, snapshot, piège de récursion, garde-fous du forfait gratuit, SEO, publicité, mesure et limites assumées.
Repère temporel : au 18 juillet 2026, la maintenance n’a pas encore eu lieu. Les résultats viennent de pannes d’origine forcées, du staging privé, de l’audit du snapshot et du passage sain en production, pas de la fenêtre réelle.
Ce que le ticket HostArmada a clarifié
La maintenance était prévue le 22 juillet 2026 de 10 h à 16 h CDT. Nous avons demandé si six heures signifiaient six heures continues, si une migration temporaire était possible, quels services seraient coupés, si une cible externe pouvait renvoyer 503 pour chaque URL, et quelles mesures de retour arrière et de crédit existaient.
Après escalade, l’administration a précisé qu’il s’agissait d’une fenêtre réservée, pas d’une durée d’arrêt garantie. L’interruption devait être plus courte mais restait imprévisible à cause des changements matériels, mises à jour et contrôles. Un aller-retour du compte pouvait créer des risques de DNS, synchronisation, e-mail et base de données.
HostArmada a proposé honnêtement un vhost sur un serveur non touché avec une page de maintenance, puis un changement manuel de l’enregistrement A au début et à la fin. Le DNS externe continuerait à résoudre, mais web, base, e-mail et panneau du serveur seraient indisponibles. Sauvegardes et reprise étaient prévues ; le crédit dépendrait de l’impact réel. C’était correct pour informer, mais manuel et sans continuité fonctionnelle.
That offer was fair for a maintenance notice. It was still manual and did not provide functional-site continuity, so we used it as the baseline to improve rather than portraying it as a provider failure.
Chronologie vérifiable : du courriel de maintenance au secours testé
Elle distingue l’annonce du fournisseur, nos questions, ce qui a été construit et testé, et l’événement réel encore à venir.
- Juillet 2026 — courriel reçu
L’avis Start Dock réservait le 22 juillet, 10 h–16 h CDT : CPU, RAM et SSD ; sécurité/logiciels web ; noyau ; nettoyage tmp/cache/logs ; optimisation. La procédure était décrite comme non réversible après démarrage.
- Serveur mutualisé Start Dock
- 22 juillet 2026, 10 h–16 h CDT
- Mises à niveau CPU, RAM et SSD
- Sécurité/logiciels du serveur web
- Mise à jour du noyau
- Nettoyage tmp, cache et logs
- Optimisation générale
- Procédure décrite comme irréversible après démarrage
- 16 juillet — questions escaladées
Durée réelle, migration, cible 503 externe, web/DB/e-mail, sauvegarde, rollback et crédit.
- 17 juillet — réponse HostArmada
Six heures étaient la fenêtre ; arrêt probablement plus court, migration écartée pour synchronisation, vhost plus A-record manuel proposé.
- Choix le 17 juillet ; suivi envoyé le 18
Worker origin-first permanent, snapshot, staging privé, collisions, 503 et rollback définis.
- 17–18 juillet — tests contrôlés
1 514 pages, 1 234 ressources, 2 748 chemins audités, panne/passage testés, récursion corrigée et apex/www fail-open actifs.
- 18 juillet — prêt, événement futur
La couche est active et testée ; la maintenance du 22 n’a pas eu lieu. Durée, trafic et revenu réels attendent les preuves après événement.


Architecture : origine d’abord, snapshot seulement en panne
Le Worker reste sur les routes racine et www. Il interroge l’origine avec un délai borné. Une réponse saine passe sans modification : PHP, sessions, en-têtes, publicité et analytics restent normaux.
En cas d’erreur réseau, timeout, 500, 502, 503, 504 ou 520–527, il cherche le même chemin dans les ressources statiques. GET et HEAD continuent ; chaque requête suivante reteste l’origine, donc la reprise est automatique.
Le snapshot n’est pas une seconde pile PHP : pas de double base inscriptible, de conflit de session ou de réconciliation après maintenance.
Flux d’une requête

Page fournisseur ou continuité Worker ?
La première suffit pour une sémantique de maintenance simple ; la seconde demande plus de préparation mais conserve la majorité des parcours de lecture et des outils côté navigateur.
| Question | Vhost temporaire du fournisseur | Worker permanent |
|---|---|---|
| Bascule | DNS manuel au début et à la fin | Automatique par requête |
| Visiteur | Une page de maintenance | Page, outil ou ressource correspondant |
| Écritures | Indisponibles | Indisponibles ; 503 explicite |
| Reprise | DNS remis manuellement | Automatique si origine saine |
| Cohérence | Risque faible sans seconde base | Risque faible sans seconde base |
| Exploitation | Simple mais action à heure fixe | Plus de préparation, peu d’action pendant l’événement |
Ce que reçoivent visiteurs et robots
Pages, outils client, CSS, scripts, images et polices viennent du snapshot avec un avis discret. Canonical et données structurées restent sur les URL d’origine.
Les écritures ne simulent pas une réussite : POST et actions indisponibles renvoient 503 Service Unavailable, Retry-After: 300 et Cache-Control: no-store, conformément au cas de maintenance temporaire défini par RFC 9110.
This distinction matters: returning a pretty 200 OK “maintenance” page for a failed form can mislead users and crawlers. Returning a controlled 503 for the unavailable action is both more honest and easier for clients to retry.
Matrice réelle de basculement
| Résultat origine | GET / HEAD | POST ou écriture |
|---|---|---|
| Sain, redirect, 4xx ou hors liste | Transmettre l’origine intacte | Transmettre l’origine intacte |
| Erreur réseau ou délai 4,5 s | Snapshot correspondant, sinon 503 | 503 + Retry-After: 300 + no-store |
| 500/502/503/504 ou 520–527 | Snapshot et en-tête diagnostic | 503 + Retry-After: 300 + no-store |
| Chemin sûr inconnu sans origine | 503 contrôlé, aucune page inventée | Sans objet |
Construction et vérification du snapshot
Nous avons exploré le site de production rendu, car l’arbre PHP local contenait des changements non publiés. Résultat : 1 514 pages, 1 234 ressources first-party, puis 2 749 fichiers pour environ 547,6 Mo, tous sous la limite par fichier.
Canonical et schema ont été conservés ; quelques liens relatifs anciens ont été réparés uniquement dans la copie. Les trackers sont retirés à la capture : seul le Worker de production ajoute GA4, AdSense et Clarity sur l’accueil, tandis que le staging privé reste sans suivi et noindex.
Tests TypeScript, unitaires, panne forcée locale, staging authentifié, navigateur, aperçu origine et audit distant complet ont été exécutés ; les 2 748 chemins publics page/ressource ont tous répondu correctement.
- Distinguer fenêtre de maintenance et panne attendue.
- Construire depuis le rendu production si local diffère.
- Inventorier pages et ressources et valider les limites.
- Garder le staging privé/noindex ; tester panne et passage normal.
- Définir méthodes, statuts, timeout, 503 et rollback.
- Éviter la récursion same-zone et garder le Host canonique.
- Choisir fail-open seulement si contourner le Worker est préférable.
- Documenter les fonctions indisponibles et actualiser la copie.

Reproduire la configuration en sécurité : étapes et code assaini
1. Définissez le contrat. Hôtes, méthodes sûres, statuts déclencheurs, délai, chemins inconnus et retrait des routes. Une réponse non-200 n’est pas forcément une panne.
2. Explorez la production rendue. Partez du sitemap canonique, découvrez uniquement les ressources same-origin HTML/CSS, normalisez, bloquez le traversal et stoppez si les limites sont dépassées.
3. Préservez le sens. Gardez canonical, hreflang, schema, liens et ressources client ; retirez service worker et tracking de la copie. Injectez publicité et analytics seulement en production.
4. Utilisez ASSETS et run_worker_first. L’origine doit être testée avant la copie ; les exemples utilisent des placeholders.
5. Évitez la récursion. Utilisez un nom DNS-only contrôlé de la même zone pour resolveOverride, URL/Host canoniques, puis testez TLS et vhost.
6. Staging privé. Secret, noindex, robots bloqué, sans publicité/analytics et comparaison explicite de l’origine.
7. Attachez apex puis www. Refusez les collisions, validez le redirect et n’utilisez fail-open que pour la disponibilité.
8. Séparez le rollback. Retirez seulement les routes possédées, gardez Worker/snapshot et révoquez les droits temporaires.
Configuration Worker/ressources assainie
{
"name": "example-host-outage-fallback",
"main": "src/index.ts",
"compatibility_date": "2026-07-17",
"assets": {
"directory": "./snapshot/dist",
"binding": "ASSETS",
"run_worker_first": true,
"html_handling": "none",
"not_found_handling": "none"
},
"vars": {
"MODE": "production",
"ORIGIN_BASE": "https://example.com",
"ORIGIN_RESOLVE_OVERRIDE": "origin-bypass.example.com",
"ORIGIN_TIMEOUT_MS": "4500"
}
}Décision origin-first et statuts
const FALLBACK_STATUSES = new Set([
500, 502, 503, 504, 520, 521, 522, 523, 524, 525, 526, 527
]);
try {
const origin = await fetch(originRequest, {
signal: AbortSignal.timeout(4500),
redirect: "manual",
cf: { resolveOverride: "origin-bypass.example.com" }
});
if (!FALLBACK_STATUSES.has(origin.status)) return origin;
return serveSnapshot(request, origin.status);
} catch {
return serveSnapshot(request);
}503 honnête pour les écritures
if (!new Set(["GET", "HEAD"]).has(request.method)) {
return new Response("Temporarily unavailable", {
status: 503,
headers: {
"Retry-After": "300",
"Cache-Control": "no-store",
"Content-Type": "text/plain; charset=utf-8"
}
});
}Construire, tester, activer et retirer
# Build from rendered production and validate the package
python scripts/build_snapshot.py
npm run types
npm run check
npx wrangler deploy --env staging --dry-run
# Deploy and test the private preview (use your own secret securely)
npx wrangler deploy --env staging
python scripts/smoke_staging.py --base "https://<private-preview>" --password "<secret>"
# Inspect, activate, or remove only the owned routes
python scripts/manage_routes.py status
python scripts/manage_routes.py activate --confirm ACTIVATE-KBT-FALLBACK
python scripts/manage_routes.py deactivate --confirm REMOVE-KBT-FALLBACKPlan de test : prouver panne, passage et reprise
Testez accueil, outil principal, CSS/JS, article, arabe RTL, longue localisation, robots, 404, HEAD, POST, redirect www et thèmes mobile.
En snapshot, vérifiez en-tête, canonical, H1, JSON-LD, ressources et avis ; en origin preview l’accès sans boucle ; en production saine l’absence du fallback et la réponse intacte.
Ne cassez jamais l’origine publique. Utilisez un preview ou une origine de test et consignez date et hash du manifeste.
Retour arrière, surveillance et reprise
Retirez uniquement les routes du Worker, sans DNS ni suppression du Worker. Vérifiez apex/www et purgez seulement si du HTML ancien subsiste.
Surveillez en-têtes, statut origine, logs, pages clés et 503. La première réponse saine reprend automatiquement. Ensuite confirmez la stabilité, révoquez les droits, archivez les mesures et renouvelez la copie.
Deux pièges : récursion same-zone et quota gratuit
Un Worker couvrant keyboardtester.click/* ne doit pas rappeler naïvement ce même hôte public. resolveOverride avec un hôte DNS-only existant dans la même zone envoie la résolution vers l’origine tout en conservant URL et Host canoniques. L’adresse d’origine et l’infrastructure de contournement doivent rester privées.
Le forfait Free autorise actuellement 100 000 requêtes Worker/jour, 20 000 fichiers statiques/version et 25 MiB/fichier. Nos 2 749 fichiers tiennent. Les routes sont fail-open : quota épuisé, Cloudflare va directement vers HostArmada plutôt que d’afficher Error 1027. Ce compromis convient à la disponibilité, pas à un contrôle de sécurité.
SEO, publicité et analytics en mode secours
Les pages disponibles restent en 200 sur les URL originales avec canonical, schema et liens. Les actions d’écriture indisponibles reçoivent 503. Aucun domaine miroir public ni nouvelle URL à soumettre.
Le staging est protégé, bloqué par robots, noindex et sans suivi. Seul le HTML de secours en production reçoit GA4 et AdSense différés ; Clarity est limité à l’accueil. Les réponses saines restent intactes. La mesure et une diffusion publicitaire restent possibles, jamais garanties.
We did not submit fallback URLs to search engines because there are no new public URLs. The continuity layer sits behind the same addresses Google already knows.
L’injection production suit le site live : GA4 après interaction ou 2 secondes, AdSense après interaction ou 15 secondes, Clarity accueil après interaction ou 12 secondes. HTMLRewriter en streaming ne modifie que le HTML GET de secours, jamais HEAD, CSS, JS ou images.
Limites et bons cas d’usage
Formulaires, IA serveur, e-mail, écritures, sessions et soumissions sauvegardées restent hors ligne sans l’origine. Un outil navigateur fonctionne seulement si tous ses fichiers sont copiés.
Le snapshot vieillit : il faut le refaire après changements importants et tester la reprise, pas seulement la panne. Une application transactionnelle exige une réplication applicative et de données.
Pour un site éditorial mutualisé riche en outils client, le compromis est bon : pas de données divisées, pas de bascule manuelle, pas de domaine dupliqué et un mode dégradé clair. Il réduit l’interruption visible sans supprimer toutes les dépendances.
Sources primaires et preuves directes
Les mesures viennent de nos manifestes et contrôles de déploiement/routes des 17–18 juillet 2026. Le comportement et les limites reposent sur la documentation primaire liée.
- Cloudflare Workers: Static Assets
- Cloudflare Workers: Platform Limits
- Cloudflare Workers Request API
- Cloudflare Workers Routes API
- RFC 9110: HTTP Semantics
- HostArmada support correspondence, July 16–17, 2026
Questions fréquentes
- Est-ce vraiment du zéro interruption sur mutualisé ?
Non. La copie de lecture reste disponible, mais formulaires, écritures, e-mail, IA et sessions ont besoin de l’origine.
- Faut-il changer le DNS pendant la panne ?
Non avec ce Worker permanent : il teste chaque requête et revient automatiquement à l’origine.
- Google voit-il une page de maintenance partout ?
Non. Les pages copiées restent en 200 avec canonical/schema ; les actions indisponibles reçoivent temporairement 503.
- Pourquoi ne pas migrer tout le compte ?
L’aller-retour peut créer des risques de DNS, fichiers, e-mail et base. Nous évitons une seconde pile inscriptible.
- Pourquoi resolveOverride ?
Pour que le Worker ne rappelle pas sa propre route. La résolution utilise un autre hôte same-zone, URL et Host restant canoniques.
- Que se passe-t-il au quota gratuit ?
Fail-open contourne le Worker vers l’origine. Le secours disparaît si l’origine est en panne, mais aucun nouveau message de quota n’est créé.
- Quand refaire le snapshot ?
Après changements majeurs et avant une maintenance, en testant panne et reprise.
La leçon n’est pas de tout mettre derrière un Worker : choisissez la plus petite couche adaptée, testez-la en privé, annoncez ses limites et automatisez la reprise.