En développement logiciel, on a souvent tendance à considérer que si un appel API renvoie une erreur, il suffit de la relancer. Dans le domaine de la messagerie télécom, et particulièrement pour le routage SMS au Maroc, cette approche naïve est destructrice.
Relancer un SMS en boucle (Retry) après un échec sans analyser la cause peut entraîner une surfacturation massive (envoyer 15 fois le même message au client), le blocage de votre compte par le mécanisme anti-spam de la passerelle, ou l'inondation d'un réseau déjà saturé.
Voici comment architecturer une gestion intelligente des échecs d'envoi SMS en environnement de production, avec des files d'attente résilientes.
Pourquoi un retry naïf peut aggraver le problème
Imaginez que Maroc Telecom (IAM) subisse une micro-coupure réseau de 2 minutes. Votre système tente d'envoyer 1000 alertes transactionnelles urgentes. L'API renvoie un timeout ou une erreur serveur HTTP 503.
Si votre code fait un simple while(failed) { retry(); }, vous allez bombarder l'API de 1000 requêtes supplémentaires chaque seconde. Dès que le réseau sera rétabli, la file d'attente de la passerelle recevra 50 000 requêtes d'un coup, ce qui la fera probablement s'effondrer à nouveau.
Distinguer erreur temporaire et permanente
Avant d'envisager un Retry, votre code doit lire le code d'erreur HTTP ou le statut DLR de l'API. C'est la règle d'or.
Ne jamais retenter (Erreur Permanente) :
HTTP 400: Le numéro de destination est mal formaté.HTTP 401 / 403: Votre clé API a expiré ou le Sender ID est bloqué.DLR Failed: L'opérateur confirme que le numéro n'existe pas.
Quand retenter (Erreur Temporaire) :
HTTP 429: Vous avez frappé la limite de débit (Rate Limit).HTTP 500 / 502 / 503: La passerelle SMS ou la liaison réseau marocaine est temporairement indisponible.
La stratégie d'Exponential Backoff
L'Exponential Backoff (recul exponentiel) est un algorithme qui espace le délai entre chaque tentative de relance. Au lieu de réessayer toutes les secondes, vous réessayez après 2 secondes, puis 4, puis 8, puis 16. On y ajoute une "Jitter" (une variation aléatoire) pour éviter que tous vos processus serveurs n'effectuent le retry exactement à la même microseconde (provoquant un nouveau pic).
Exemple d'implémentation avec Laravel Horizon / BullMQ
Dans les architectures modernes, on ne gère pas le retry dans le contrôleur HTTP. On pousse le message dans un Message Broker (comme Redis) et on laisse un Worker s'en occuper.
En PHP (Laravel Queues)
Laravel gère l'exponential backoff de manière élégante directement dans les propriétés de vos "Jobs".
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendSmsNotification implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $phoneNumber;
public $message;
// Nombre maximal de tentatives (ex: abandonner après 5 essais)
public $tries = 5;
// Algorithme de recul : réessayer après 2s, 10s, 30s, 60s
public function backoff()
{
return [2, 10, 30, 60];
}
public function handle()
{
$response = EnvoiSmsApi::send($this->phoneNumber, $this->message);
// Si l'API renvoie un 400 (erreur permanente), on abandonne tout de suite
if ($response->status === 400) {
$this->fail(new \Exception('Numéro invalide, abandon.'));
return;
}
// Si c'est une erreur 503, la fonction va naturellement throw une exception
// et Laravel replacera le Job dans la file d'attente avec le backoff prévu.
if (!$response->successful()) {
throw new \Exception('Erreur temporaire API.');
}
}
}La règle de péremption de l'OTP
Si vous gérez l'envoi de codes OTP pour l'authentification 2FA, un retry peut être dangereux. Si le SMS finit par arriver 15 minutes plus tard après 4 retries réseau, le code généré dans votre base de données aura déjà expiré, générant de la frustration chez le client.
Pour les OTP critiques, limitez les tries à 2 maximum, et si cela échoue, implémentez plutôt un Fallback métier (proposer un appel vocal ou un envoi WhatsApp) directement sur l'interface de l'utilisateur, plutôt que de retenter l'envoi SMS en silence.
Questions fréquentes
Comment suivre l'acheminement sur les réseaux IAM, Inwi et Orange ?
Nos routes locales vers Maroc Telecom (IAM), Orange et inwi, avec bascule automatique entre routes, renvoient un statut de livraison opérateur pour chaque message, par webhook. Le délai de remise dépend de l'opérateur et du réseau du destinataire.
Comment la plateforme gère-t-elle le format des numéros marocains ?
EnvoiSMS normalise automatiquement les numéros saisis (06..., 07..., 00212...) vers le standard E.164 (+212) pour éviter tout échec de distribution.