« Cela peut parfois prendre jusqu'à 72 heures », écrit DigiCert à propos de la propagation DNS. Hostinger annonce jusqu'à 24 heures, et 72 « dans de rares cas ». Namecheap titre une section « Why does it take up to 72 hours? », puis parle de 24 à 48 heures dans son texte. Aucune ne rattache ces 72 heures à une valeur de TTL ou à une règle du protocole. La seule fourchette de cet ordre lue dans les standards vise autre chose : 1 à 3 jours de réponses périmées dans la RFC 8767, quand les autoritaires ne répondent plus, option désactivée par défaut dans Unbound et BIND. Personne ne pousse une modification vers les résolveurs : ils gardent une réponse le temps qu'on les y autorise, puis redemandent.
Une propagation DNS dure au plus l'ancien TTL de l'enregistrement modifié, compté depuis la dernière lecture de chaque résolveur, si ce résolveur respecte le TTL. Un nom qui n'existait pas attend au plus le minimum entre le TTL du SOA et son champ MINIMUM, dans la limite du plafond du résolveur. Pour un changement de serveurs de noms, la borne vient du TTL de délégation publié par le parent : 172800 secondes lues pour example.com sous .com, 3600 pour afnic.fr sous .fr. Au banc, Unbound a suivi ce TTL, BIND le plus court des TTL du parent et de la zone.
Sur un domaine réel, on ne connaît ni l'heure de remplissage des caches ni la politique des résolveurs. D'où un banc local, où l'on tient la zone et le résolveur.
Le banc : racine, zone et résolveur dans un seul conteneur
named n'écoute que sur des adresses présentes sur une interface : il lui faut NET_ADMIN et des alias de boucle locale.
docker run --rm -it --cap-add NET_ADMIN alpine:3 sh
apk add -q bind bind-tools unbound
for ip in 2 10 53; do ip addr add 127.0.0.$ip/32 dev lo; done
srv() { # name ip zone-statements
mkdir -p /lab/$1
cat > /lab/$1/named.conf <<EOF
options { directory "/lab/$1"; pid-file "named.pid"; session-keyfile none;
listen-on { $2; }; listen-on-v6 { none; }; recursion no;
dnssec-validation no; };
controls { };
$3
EOF
named -4 -c /lab/$1/named.conf
}
mkdir -p /lab/racine /lab/ns1
cat > /lab/racine/racine.zone <<'EOF'
$TTL 3600
. IN SOA a.racine. admin.racine. 1 3600 600 86400 300
. IN NS a.racine.
a.racine. IN A 127.0.0.2
labo.test. 120 IN NS ns1.labo.test.
ns1.labo.test. 120 IN A 127.0.0.10
EOF
cat > /lab/ns1/labo.zone <<'EOF'
$TTL 300
labo.test. 300 IN SOA ns1.labo.test. admin.labo.test. 1 3600 600 86400 60
labo.test. 300 IN NS ns1.labo.test.
ns1.labo.test. 300 IN A 127.0.0.10
www.labo.test. 120 IN A 192.0.2.10
EOF
srv racine 127.0.0.2 'zone "." { type primary; file "racine.zone"; };'
srv ns1 127.0.0.10 'zone "labo.test" { type primary; file "labo.zone"; };'
printf '. 3600000 NS a.racine.\na.racine. 3600000 A 127.0.0.2\n' > /lab/hints
cat > /lab/unbound.conf <<'EOF'
server:
interface: 127.0.0.53
do-ip6: no
username: ""
chroot: ""
do-not-query-localhost: no
root-hints: /lab/hints
module-config: "iterator"
local-zone: "test." nodefault
EOF
unbound -c /lab/unbound.conf
Pour modifier la zone : éditer /lab/ns1/labo.zone, incrémenter le numéro de série, puis kill -HUP "$(cat /lab/ns1/named.pid)". On interroge l'autoritaire sur @127.0.0.10 et Unbound sur @127.0.0.53.
Les sorties ci-dessous viennent d'un banc plus large, passé le 2 novembre 2026 avec BIND 9.20.30, Unbound 1.25.2 et DiG 9.20.30 : zone test. intermédiaire, résolveur BIND sur 127.0.0.54, second autoritaire sur 127.0.0.11. Sans local-zone: "test." nodefault, Unbound répond lui-même NXDOMAIN sur ce nom réservé. La validation DNSSEC est coupée parce que la racine est factice, un réglage de banc à ne pas reprendre en production.
L'autoritaire répète, le résolveur décompte
$ dig www.labo.test A @127.0.0.10 | grep '^;; flags'
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
--- 17:56:49
auth www.labo.test. 120 IN A 192.0.2.10
unbound www.labo.test. 120 IN A 192.0.2.10
bind www.labo.test. 120 IN A 192.0.2.10
--- 17:57:14
auth www.labo.test. 120 IN A 192.0.2.10
unbound www.labo.test. 95 IN A 192.0.2.10
bind www.labo.test. 95 IN A 192.0.2.10
L'autoritaire porte le drapeau aa et répond toujours 120, la valeur de la zone. Le résolveur répond avec qr rd ra, sans aa, et son chiffre descend au rythme de l'horloge : il lui reste ce temps avant de redemander. Ses réponses sortent en 0 ms, il n'interroge personne.
En production, on fait la même comparaison : dig +norecurse sur l'autoritaire, dig sur le résolveur. Le reste de la lecture de dig est dans notre guide de dépannage DNS.
Deux résolveurs basculent à deux heures différentes
Même zone, TTL de 120. Unbound lit l'enregistrement, BIND le lit 40 secondes plus tard, et l'adresse change dans la même seconde.
fill unbound 17:58:16: www.labo.test. 120 IN A 192.0.2.10
fill bind 17:58:56: www.labo.test. 120 IN A 192.0.2.10
changed 17:58:56: www.labo.test. 120 IN A 198.51.100.20
unbound: www.labo.test. 80 IN A 192.0.2.10
bind: www.labo.test. 120 IN A 192.0.2.10
+80s unbound NOERROR 198.51.100.20
+119s bind NOERROR 198.51.100.20
Le résolveur qui a lu 40 secondes avant le changement bascule à +80 s, celui qui venait de lire à +119 s. Chaque cache attend ce qu'il lui reste de TTL. Le pire cas vaut bien un TTL complet, pour le résolveur qui a lu juste avant vous.
Baisser le TTL en même temps que l'adresse n'achète rien
Essayons le réflexe de dernière minute, TTL à 10 secondes et nouvelle adresse dans la même édition de zone.
lowered and changed 18:01:06: www.labo.test. 10 IN A 198.51.100.20
unbound: www.labo.test. 120 IN A 192.0.2.10
bind: www.labo.test. 120 IN A 192.0.2.10
+119s bind NOERROR 198.51.100.20
+120s unbound NOERROR 198.51.100.20
Le nouveau TTL voyage avec la nouvelle réponse : un résolveur ne le découvre qu'en redemandant, donc à la fin de l'ancien. Même zone, cette fois avec la baisse 125 secondes avant le changement :
lowered only 18:03:18
unbound: www.labo.test. 10 IN A 192.0.2.10
bind: www.labo.test. 10 IN A 192.0.2.10
changed 18:05:23
+9s bind NOERROR 198.51.100.20
+10s unbound NOERROR 198.51.100.20
L'attente tombe de 120 à 10 secondes, douze fois moins. On baisse donc au moins un ancien TTL complet avant le changement : à 86400 secondes, 24 heures avant.
Le NXDOMAIN qu'on s'est servi soi-même
Un nom interrogé avant d'exister laisse une trace. Le résolveur garde aussi la réponse négative, et la RFC 2308 fixe sa durée : « the minimum of the SOA.MINIMUM field and SOA's TTL ». Ici, un SOA de TTL 300 et de MINIMUM 60 :
$ dig nouveau.labo.test A @127.0.0.53 | grep -E 'status|SOA'
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 12358
labo.test. 60 IN SOA ns1.labo.test. admin.labo.test. 1 3600 600 86400 60
added 18:05:59: nouveau.labo.test. 300 IN A 203.0.113.30
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 62949
labo.test. 45 IN SOA ns1.labo.test. admin.labo.test. 1 3600 600 86400 60
+45s unbound NOERROR 203.0.113.30
+45s bind NOERROR 203.0.113.30
L'enregistrement existe sur l'autoritaire, et le résolveur nie encore 45 secondes. Le décompte se lit sur la ligne du SOA, en section autorité.
On teste nouveau.exemple.fr, on constate l'échec, on crée l'enregistrement, on reteste : le premier test a causé l'attente. Le NXDOMAIN vaut pour le nom, le NODATA pour un couple nom et type : un TXT absent demandé sur www revient en NOERROR avec le même SOA. Un défi DNS-01 avec certbot et Let's Encrypt vérifié trop tôt tombe dans l'un de ces deux cas.
La formule et les plafonds se vérifient aussi :
SOA TTL 300 MINIMUM 86400
labo.test. 300 IN SOA ns1.labo.test. admin.labo.test. 7 3600 600 86400 86400
SOA TTL 86400 MINIMUM 86400
@127.0.0.10
labo.test. 86400 IN SOA ns1.labo.test. admin.labo.test. 8 3600 600 86400 86400
@127.0.0.53
labo.test. 3600 IN SOA ns1.labo.test. admin.labo.test. 8 3600 600 86400 86400
@127.0.0.54
labo.test. 10800 IN SOA ns1.labo.test. admin.labo.test. 8 3600 600 86400 86400
3600 et 10800 sont les défauts documentés, cache-max-negative-ttl pour Unbound et max-ncache-ttl pour BIND. Pour un domaine interrogé avant son enregistrement, le SOA du registre fixe la durée : TTL 900 et MINIMUM 900 sur com., TTL 3600 et MINIMUM 600 sur fr., relevés le 2 novembre 2026. Soit 900 et 600 secondes de cache négatif possible.
Changer de NS : l'attente passe par le parent
Un changement de serveurs de noms se règle dans la zone parente, dont le TTL ne vous appartient pas :
$ dig +norecurse +noall +authority example.com NS @a.gtld-servers.net
example.com. 172800 IN NS hera.ns.cloudflare.com.
$ dig +norecurse +noall +authority afnic.fr NS @d.nic.fr
afnic.fr. 3600 IN NS ns1.nic.fr.
Cela fait 48 heures pour l'un, une heure pour l'autre. Au banc, l'ancien et le nouvel autoritaire servent deux adresses différentes, avec un TTL de 5 secondes sur www pour écarter le cache de l'enregistrement. Avec un TTL de 120 chez le parent et de 30 sur les NS de la zone :
parent moved 18:10:26
labo.test. 120 IN NS ns.heb-b.test.
+28s bind NOERROR 198.51.100.20
+118s unbound NOERROR 198.51.100.20
Unbound suit le parent, BIND le TTL le plus court. Dans l'autre sens, 30 chez le parent et 120 dans la zone, les deux basculent à +28 s. Des NS internes à la zone, avec colle, donnent les mêmes écarts. Baisser le TTL des NS dans sa zone n'a donc rien changé pour Unbound. Ces résultats valent pour un autoritaire BIND, qui joint ses NS aux réponses non récursives (minimal-responses par défaut). Un autoritaire qui s'en abstient n'a pas été mesuré.
Pendant ces 118 secondes, l'ancien serveur a reçu 28 requêtes : un résolveur en retard sur la délégation continue d'y aller. Avec l'ancien serveur coupé dès la bascule, trois passages identiques, TTL de 120 des deux côtés :
parent moved 18:13:35
old server stopped 18:13:35
+3s unbound
+3s bind SERVFAIL
+12s unbound NOERROR 198.51.100.20
+119s bind NOERROR 198.51.100.20
La ligne vide d'Unbound signale une sonde sans réponse sous 2 secondes, puis il trouve le nouveau serveur de lui-même. BIND rend SERVFAIL jusqu'à la fin du TTL : presque deux minutes de panne franche. Sous .com, un résolveur qui suit le parent peut retourner chez l'ancien serveur pendant ces 48 heures, dans la limite de son plafond (cache-max-ttl, 86400 chez Unbound). Ce cas-là, on l'a calculé sans le mesurer.
On laisse l'ancien autoritaire allumé, avec les mêmes données que le nouveau, pendant au moins le plus long des deux TTL de NS, compté depuis la publication chez le parent. Une zone signée ajoute le DS, publié lui aussi chez le parent : ce banc sans DNSSEC ne couvre pas cette chaîne de confiance.
Les écarts que le TTL de la zone n'explique pas
Avant le cache, il y a parfois un secondaire en retard, et donc un autoritaire qui répond l'ancienne valeur en toute bonne foi. Avec un REFRESH de 300 secondes, le défaut de min-refresh-time chez BIND :
NOTIFY: serial 41 on secondary after +0s
no NOTIFY: serial 42 on secondary after +291s
Un second passage a donné +274 s. Si deux autoritaires donnent deux numéros de série, le problème vient de la notification RFC 1996 ou du transfert, pas d'un cache.
Un résolveur peut aussi garder plus longtemps qu'on ne le lui demande : Unbound avec cache-min-ttl: 600 a rendu un TTL de 600 sur une zone à 60. Ce réglage vaut 0 par défaut, comme min-cache-ttl chez BIND.
Les caches du système et du navigateur n'ont pas été mesurés ici. dig @résolveur les contourne, un utilisateur non : si cette requête donne la bonne adresse et que le navigateur reste sur l'ancienne, le DNS public n'est plus en cause.
Google Public DNS et 1.1.1.1 ont chacun un formulaire de purge, qui ne vaut que pour eux.
Bascule d'un A ou d'un NS : l'ordre des gestes
Pour un enregistrement, quatre étapes dans cet ordre :
- Lire le TTL actuel sur l'autoritaire :
dig +norecurse +noall +answer www.exemple.fr A @ns1.exemple.fr. - Le baisser, pour le
Acomme pour leAAAA, puis attendre cet ancien TTL en entier. - Changer l'adresse, puis vérifier l'autoritaire avant tout résolveur.
- Remonter le TTL une fois la nouvelle adresse confirmée.
Pour des NS, le contrôle qui compte interroge un serveur du registre en +norecurse, comme plus haut : tant qu'il répond l'ancienne délégation, l'horloge n'a pas démarré.
Une migration de serveurs qui inclut cette bascule DNS se planifie aussi dans l'infogérance de serveurs SHPV.
Sources
- RFC 2181 : le TTL est un maximum (section 8).
- RFC 2308 : cache négatif, TTL calculé à partir du SOA.
- RFC 1996 : NOTIFY entre primaire et secondaires.
- RFC 8767 : réponses périmées.
- Référence BIND 9 : défauts de
max-ncache-ttl,min-cache-ttl,min-refresh-time,minimal-responses,stale-answer-enable. - unbound.conf(5) : défauts de
cache-max-ttl,cache-max-negative-ttl,cache-min-ttl,serve-expired, zone localetest. - DigiCert : « jusqu'à 72 heures ».
- Hostinger : 72 heures « dans de rares cas ».
- Namecheap : un titre à 72 heures sur un texte à 24 ou 48.


