Redis managé et Serverless SQL
Pourquoi
Deux constats sur Signalements en production, un an après sa mise en ligne.
Le premier vient des graphiques de la base. La page d'accueil de chaque métropole affiche les cinquante derniers signalements de son territoire. Elle est demandée des milliers de fois par heure, et chaque demande refait la même requête sur PostgreSQL, alors que la liste ne change que quelques fois par heure. Le lendemain d'un orage, ces lectures identiques occupent la base au moment où elle doit enregistrer des centaines de nouveaux signalements. Par ailleurs, un script mal écrit d'un partenaire a envoyé dix mille requêtes en une minute, et il n'existe aucun moyen de limiter le débit d'un client.
Le second vient de la facture. La préproduction de chaque application a sa propre base PostgreSQL managée, allumée 24 heures sur 24, pour être utilisée quelques heures par semaine, quand une métropole valide une version. Elle coûte le même prix qu'une base qui travaille.
Deux produits de Scaleway répondent à ces besoins : Managed Database for Redis, une base en mémoire, pour le cache et les compteurs ; Serverless SQL Database, un PostgreSQL qui s'arrête de lui-même quand personne ne l'utilise. Aucun ne remplace la base principale ; chacun a des limites que la documentation dit clairement, et qu'il faut connaître avant de s'en servir.
Les concepts
Pourquoi un cache
Un cache garde une copie de données coûteuses à obtenir dans un stockage rapide, pour les servir sans recalcul. Redis stocke ses données en mémoire vive : une lecture y prend une fraction de milliseconde, quand la même requête sur PostgreSQL demande l'analyse de la requête, un plan d'exécution et des lectures de pages.
Le schéma le plus courant, que la FAQ de Scaleway décrit, s'appelle cache-aside (le cache à côté) :
sequenceDiagram
participant A as Signalements
participant R as Redis
participant P as PostgreSQL
A->>R: GET derniers:metropole-42
alt présent
R-->>A: liste (moins d'une ms)
else absent
R-->>A: rien
A->>P: SELECT ... ORDER BY cree_le DESC LIMIT 50
P-->>A: liste
A->>R: SET derniers:metropole-42 liste EX 60
end
L'application lit d'abord le cache ; en cas d'absence, elle interroge la base et range le résultat dans le cache, avec une durée de vie (EX 60 : 60 secondes). Le cache n'est jamais la source de vérité : on peut le vider à tout moment sans perdre de données, seulement de la performance.
La difficulté est connue sous le nom d'invalidation : quand la donnée change, la copie est fausse. Trois stratégies, combinables :
| Stratégie | Principe | Pour Signalements |
|---|---|---|
| Expiration | La copie expire après une durée | Une liste vieille de 60 secondes au plus : acceptable pour une page d'accueil |
| Invalidation à l'écriture | L'application supprime la clé quand elle modifie la donnée | À la création d'un signalement, DEL derniers:metropole-42 |
| Écriture traversante | L'application met à jour le cache et la base ensemble | Plus complexe, rarement utile ici |
Redis managé chez Scaleway
Au 5 octobre 2026, le produit s'appelle Managed Database for Redis™. Le journal des changements de Scaleway annonce la prise en charge de Redis 8.4 le 19 février 2026, et le même jour la dépréciation de la version 7.2.11, en invitant à passer à 8.4. Un point de contexte : depuis la version 7.4, Redis n'est plus distribué sous licence BSD ; Redis 8 l'est sous trois licences au choix, dont l'AGPLv3, selon la page des licences de Redis. Un groupe de contributeurs a créé en 2024, sous l'égide de la Linux Foundation, Valkey, une bifurcation de Redis 7.2 sous licence BSD, que d'autres fournisseurs proposent. La documentation de Scaleway ne mentionne pas Valkey à cette date.
Le service est zonal : il est disponible dans les zones fr-par-1, fr-par-2, nl-ams-1, nl-ams-2, pl-waw-1 et pl-waw-2. Il existe en trois modes :
| Mode | Nœuds | Réplication | Ce qu'il protège |
|---|---|---|---|
| Nœud seul (standalone) | 1 | Aucune | Rien : une panne vide le cache |
| Haute disponibilité | 2, d'après la FAQ | Asynchrone vers un nœud de secours | La panne d'un nœud, avec perte possible des dernières écritures |
| Cluster | 3 à 6 | Chaque nœud porte un primaire et le réplica d'un autre | La panne d'un nœud, et la mémoire au-delà d'une seule machine |
En mode cluster, l'espace des clés est découpé en 16 384 emplacements (hash slots), répartis entre les primaires ; une clé appartient à l'emplacement donné par une somme de contrôle de son nom. Le client doit savoir parler au cluster : un client Redis ordinaire, connecté à un seul nœud, reçoit des redirections (MOVED) qu'il ne sait pas suivre. La FAQ le rappelle : il faut un connecteur compatible cluster.
La mémoire pleine : l'éviction
Redis travaille dans une quantité de mémoire bornée (maxmemory). Quand elle est pleine, la politique d'éviction (maxmemory-policy) décide de ce qui se passe à la prochaine écriture. La documentation de Redis en décrit plusieurs ; les plus utiles :
| Politique | Comportement |
|---|---|
noeviction | Les écritures échouent avec une erreur ; les lectures continuent (valeur par défaut de Redis) |
allkeys-lru | Supprime les clés les moins récemment utilisées, parmi toutes |
volatile-lru | Idem, mais seulement parmi les clés qui ont une durée de vie |
allkeys-lfu | Supprime les clés les moins fréquemment utilisées |
volatile-ttl | Supprime les clés les plus proches de leur expiration |
Pour un cache pur, allkeys-lru est le choix naturel : le cache garde ce qui sert. Si la même instance stocke aussi des compteurs qu'on ne veut pas perdre (la limitation de débit, plus bas), volatile-lru protège les clés sans durée de vie. Le réglage se fait par les paramètres avancés de Scaleway, avec maxclients et tcp-keepalive. La page de documentation ne précise pas la valeur par défaut de la politique sur le service de Scaleway ; la commande scw redis version list-settings liste, pour une version, les paramètres disponibles avec leur valeur par défaut : consultez-la avant de créer l'instance.
La persistance : ce qu'elle promet, et ce qu'elle ne promet pas
Redis sait écrire ses données sur disque, par instantanés périodiques (le format RDB) ou par journal des commandes (AOF). Sur le service de Scaleway, des instantanés sont pris selon une configuration fixe : toutes les 900 secondes si une clé a changé, 300 secondes si dix clés ont changé, 60 secondes si dix mille clés ont changé, et l'on peut les désactiver (disable-save). Mais la documentation est explicite :
« Scaleway Managed Database for Redis™ is currently best suited for caching use cases. The data persistence mechanism presented on this page do not guarantee data recovery in case of incident. »
Autrement dit : ne mettez dans ce Redis que ce que vous pouvez perdre. Un cache, des compteurs de limitation de débit, des sessions si les utilisateurs acceptent de se reconnecter. Pas une file de signalements en attente d'enregistrement, ni quoi que ce soit dont la seule copie serait là.
Serverless SQL Database
Serverless SQL Database est un PostgreSQL managé dont les ressources de calcul varient avec la charge et descendent à zéro au repos. La page de présentation et les concepts de Scaleway en décrivent le fonctionnement :
- une base sans requête pendant 5 minutes passe à l'état inactif (idle) ; la facturation du calcul s'arrête, celle du stockage continue ;
- la première requête suivante réveille la base : c'est le démarrage à froid, « généralement moins de cinq secondes » ;
- en activité, la base monte de 25 % de vCPU et de mémoire quand elle utilise plus de 90 % de ses vCPU pendant 10 secondes, et descend de 25 % sous 70 %, au plus une fois par minute, entre un minimum et un maximum que l'on fixe ; 4 Go de mémoire par vCPU, de 0 à 15 vCPU ;
- jusqu'à 1 To de stockage et 1 000 connexions, grâce à un regroupement de connexions intégré ;
- une sauvegarde logique automatique par jour, conservée 7 jours, comprise dans le prix du stockage, exportable au format de
pg_dump.
Au 5 octobre 2026, la CLI 2.62 ne propose ce produit que dans la région fr-par. Les identifiants ne sont pas des comptes PostgreSQL : l'utilisateur est l'identifiant d'un principal IAM (utilisateur ou application), et le mot de passe est une clé secrète d'API. Les droits se donnent par des jeux de permissions IAM : ServerlessSQLDatabaseReadOnly, ServerlessSQLDatabaseDataReadWrite (les données seulement), ServerlessSQLDatabaseReadWrite (données et structure des tables), ServerlessSQLDatabaseFullAccess. La connexion passe par Internet, en TLS ; la documentation ne décrit pas de point d'accès sur réseau privé.
Ce fonctionnement a un prix, que la page Known differences détaille. Parmi les différences avec un PostgreSQL ordinaire :
- pas de tables ni de vues temporaires ;
LISTENetNOTIFYfonctionnent sans garantie de remise ;- les verrous consultatifs (
pg_advisory_lock) ne sont pas garantis, ce qui rend peu sûrs les outils qui s'en servent, dont le stockage d'état de Terraform dans PostgreSQL ; - pas d'abonnement de réplication logique, pas de transactions préparées ;
- pas de commandes de définition des bases ni des utilisateurs en SQL (
CREATE USER,GRANT) : tout passe par IAM et l'API ; - une requête SQL ne dépasse pas 1 024 Ko.
En pratique
On ajoute un cache Redis à la production, sur le réseau privé, puis une base Serverless SQL pour la préproduction. Les commandes ont été vérifiées avec l'aide de scw 2.62 et le SDK Go ; elles créent des ressources facturées.
Créer l'instance Redis
Le mot de passe est obligatoire à la création, et la CLI ne propose pas de le générer pour Redis : on le génère soi-même, sans qu'il apparaisse dans l'historique du shell.
$ read -rs REDIS_MDP < <(openssl rand -base64 24 | tr -d '/+=' | cut -c1-24; echo)
$ PN=$(scw vpc private-network list name=pn-signalements region=fr-par -o json \
| jq -r '.[] | select(.name == "pn-signalements") | .id')
$ scw redis cluster create name=sig-cache version=8.4.0 node-type=RED1-MICRO \
user-name=signalementsApp1 password="$REDIS_MDP" \
cluster-size=1 tls-enabled=true \
endpoints.0.private-network.id="$PN" \
endpoints.0.private-network.enable-ipam=true \
tags.0=app=signalements zone=fr-par-1 --wait
Chaque argument :
version=8.4.0: la version annoncée par le journal des changements ;scw redis version listdonne la liste exacte disponible dans votre zone. Le nom du type de nœud (RED1-MICRO) suit la FAQ, qui rangeRED1-MICROàRED1-Sparmi les nœuds de développement etRED1-MàRED1-XLparmi ceux de production ;scw redis node-type listdonne la liste à jour, avec l'écriture exacte des noms (la FAQ écritRED1-micro), à reprendre telle quelle.user-name: la documentation impose de 12 à 63 caractères, commençant par une lettre, avec au moins une majuscule et une minuscule ;scalewayadminetmetricssont réservés.password="$REDIS_MDP": la valeur est lue depuis une variable, mais attention, elle apparaît dans la liste des processus pendant l'exécution de la commande. Sur un poste partagé, préférez la console. Rangez-la ensuite dans Secret Manager (leçon 8).cluster-size=1: un nœud seul, suffisant pour un cache qu'on peut perdre. La haute disponibilité (deux nœuds, d'après la FAQ) ou un cluster (3 à 6) se justifient quand la perte du cache surchargerait la base.tls-enabled=true: le chiffrement du transport. Sans lui, mots de passe et données circulent en clair sur le réseau privé.endpoints.0.private-network...: un point d'accès sur le réseau privé, à adresse attribuée par IPAM. La page de création indique qu'on ne peut pas rattacher l'instance à un réseau privé après sa création, alors que la FAQ dit l'inverse pour un nœud seul : créez-la directement sur le réseau privé, la question ne se posera pas. La FAQ précise aussi que le service ne prend pas en charge le routage entre réseaux privés d'un VPC ni l'appairage de VPC (leçon 13) : les clients doivent être sur le même réseau privé.
Récupérez l'adresse, le port et le certificat :
$ CACHE=$(scw redis cluster list name=sig-cache zone=fr-par-1 -o json \
| jq -r '.[] | select(.name == "sig-cache") | .id')
$ scw redis cluster get "$CACHE" zone=fr-par-1 -o json \
| jq '.endpoints[] | {ips, port, prive: (.private_network != null)}'
$ scw redis cluster get-certificate "$CACHE" zone=fr-par-1 > sig-cache.pem
Depuis une instance du réseau privé, testez avec redis-cli, comme le montre la documentation :
$ redis-cli -h <ip privée> -p <port> --user signalementsApp1 --askpass --tls --cacert sig-cache.pem PING
--askpass demande le mot de passe sans l'afficher ; --tls --cacert vérifie le certificat du serveur. La réponse attendue est PONG.
Régler l'éviction
Le cache ne doit jamais refuser une écriture parce qu'il est plein :
$ scw redis setting add cluster-id="$CACHE" \
settings.0.name=maxmemory-policy settings.0.value=volatile-lru zone=fr-par-1
volatile-lru plutôt que allkeys-lru : les listes en cache ont toutes une durée de vie et peuvent être évincées ; les compteurs de limitation de débit, eux aussi, ont une durée de vie courte. Toutes les clés que pose l'application en ont une : c'est une règle de code à vérifier en revue.
Brancher Signalements
Côté application, la variable REDIS_URL prend la forme rediss://<utilisateur>:<mot de passe>@<ip privée>:<port>/0 (le double s de rediss signifie TLS), et le code applique le cache-aside. Avec le client Python redis :
import json
import redis
cache = redis.Redis.from_url(REDIS_URL, ssl_ca_certs="/etc/signalements/sig-cache.pem")
def derniers_signalements(metropole_id):
cle = f"derniers:{metropole_id}"
en_cache = cache.get(cle)
if en_cache is not None:
return json.loads(en_cache)
liste = requete_postgresql(metropole_id) # la requête existante
cache.set(cle, json.dumps(liste), ex=60) # 60 secondes de vie
return liste
def creer_signalement(metropole_id, donnees):
enregistrer_postgresql(metropole_id, donnees)
cache.delete(f"derniers:{metropole_id}") # invalidation à l'écritureSi Redis est indisponible, l'application doit continuer sans lui : on entoure les appels au cache d'une gestion d'erreur qui retombe sur la base. Un cache qui fait tomber l'application quand il tombe est devenu une dépendance, pas une optimisation.
Limiter le débit
Le compteur à fenêtre fixe est la limitation la plus simple : au plus 600 requêtes par minute et par clé d'API partenaire.
def autorise(cle_api, limite=600):
fenetre = int(time.time() // 60)
cle = f"debit:{cle_api}:{fenetre}"
n = cache.incr(cle) # atomique : incrémente et renvoie la nouvelle valeur
if n == 1:
cache.expire(cle, 120) # la clé disparaît après la fenêtre
return n <= limiteINCR est atomique dans Redis : deux instances de Signalements qui incrémentent la même clé en même temps ne perdent aucun compte, parce que Redis exécute les commandes une par une. C'est ce qui rend Redis adapté à ce rôle, et c'est pourquoi le compteur doit vivre dans Redis et non dans la mémoire de chaque instance du groupe d'autoscaling (leçon 2) : chacune compterait de son côté. La fenêtre fixe laisse passer jusqu'au double de la limite à cheval sur deux minutes ; des algorithmes à fenêtre glissante corrigent ce défaut au prix d'un peu plus de code.
Créer la base Serverless SQL de préproduction
$ scw sdb-sql database create name=signalements-preprod cpu-min=0 cpu-max=4 region=fr-par
$ SDB=$(scw sdb-sql database list region=fr-par -o json \
| jq -r '.[] | select(.name == "signalements-preprod") | .id')
$ scw sdb-sql database get "$SDB" region=fr-par -o json | jq '{endpoint, status, cpu_min, cpu_max, cpu_current}'
cpu-min=0: la base descend à zéro vCPU au repos, et ne coûte alors que son stockage. Le prix est le démarrage à froid de quelques secondes : acceptable pour une préproduction, pas pour une API de production. Aveccpu-min=1, plus de démarrage à froid, mais une facturation continue.cpu-max=4: un plafond, qui borne aussi la facture si un test de charge s'emballe.- Le champ
endpointcontient l'adresse de connexion, de la forme<identifiant>.pg.sdb.fr-par.scw.cloudd'après la documentation TLS.
Pour se connecter, il faut un principal IAM et une clé. L'application de préproduction reçoit une identité dédiée, limitée aux données :
$ APP=$(scw iam application create name=sig-preprod-sdb -o json | jq -r .id)
$ scw iam policy create name=sig-preprod-sdb application-id="$APP" \
rules.0.project-ids.0="$PREPROD" \
rules.0.permission-set-names.0=ServerlessSQLDatabaseReadWrite
$ scw iam api-key create application-id="$APP" expires-at=2026-12-31T00:00:00Z \
description="Signalements préproduction : Serverless SQL" -o json > .tmp/cle-sdb.json
La DATABASE_URL de la préproduction devient alors :
postgresql://<id de l'application>:<clé secrète>@<endpoint>:5432/<nom de la base>?sslmode=verify-full&sslrootcert=systemsslmode=verify-full vérifie le certificat et le nom du serveur ; sslrootcert=system (PostgreSQL 16 et plus récent côté client) fait confiance aux autorités du système, puisque le certificat est émis par Let's Encrypt, d'après la documentation. ServerlessSQLDatabaseReadWrite permet aux migrations de créer des tables ; pour une application qui ne touche qu'aux données, ServerlessSQLDatabaseDataReadWrite suffit. Le port 5432 est le port standard de PostgreSQL ; vérifiez-le dans la console, qui affiche la chaîne de connexion complète.
Charger les données et tester la compatibilité
On charge dans la préproduction une copie anonymisée de la production, avec pg_restore :
$ pg_restore --no-owner --no-privileges --dbname="$DATABASE_URL_PREPROD" signalements-anonymise.dump
--no-owner et --no-privileges sont indispensables : la base Serverless refuse les commandes de gestion des rôles et des droits, que contient un export ordinaire. Si le chargement échoue sur une table temporaire, une extension non prise en charge ou une transaction préparée, la page Known differences donne la raison. C'est aussi le moment de lancer la suite de tests de Signalements contre cette base : une différence de compatibilité découverte en préproduction est une information, découverte en production un incident.
Nettoyer
$ scw redis cluster delete "$CACHE" zone=fr-par-1
$ scw sdb-sql database delete "$SDB" region=fr-par
Gardez-les si vous poursuivez : la leçon 14 en affiche les métriques.
Sous le capot
Pourquoi Redis est si rapide, et ce que cela implique. Redis garde toutes ses données en mémoire et exécute les commandes une par une, dans un seul fil d'exécution principal : pas de verrou, pas de lecture disque sur le chemin d'une requête. C'est ce qui rend INCR atomique sans effort. La contrepartie : une commande lente (un KEYS * sur des millions de clés, un SMEMBERS sur un ensemble énorme) bloque toutes les autres pendant son exécution. En production, on n'utilise jamais KEYS, mais SCAN, qui parcourt par petits lots.
L'éviction est approximative. Redis ne tient pas une liste exacte des clés par date d'usage, trop coûteuse en mémoire : pour évincer, il tire un échantillon de clés et supprime la meilleure candidate de l'échantillon (cinq clés par défaut, réglage maxmemory-samples), selon la documentation de Redis. Le résultat est proche d'un vrai LRU, à moindre coût.
Ce que fait une base serverless au repos. Pour descendre à zéro, le calcul et le stockage sont séparés : le stockage reste en place, le calcul est libéré, et la connexion du client est tenue par le regroupeur de connexions, qui ne dort pas. Quand une requête arrive, le regroupeur réveille un moteur, qui rattache le stockage ; d'où les quelques secondes de démarrage à froid, et la documentation précise que les connexions établies sont maintenues pendant ces changements. Ce regroupement explique aussi les différences de compatibilité : plusieurs clients partagent les mêmes sessions de moteur, et tout ce qui dépend de l'état d'une session (tables temporaires, verrous consultatifs, LISTEN) devient incertain.
Les identifiants IAM dans le protocole de PostgreSQL. Le protocole de PostgreSQL ne connaît que des noms d'utilisateur et des mots de passe. Scaleway y place un identifiant de principal et une clé secrète, vérifiés par le regroupeur auprès d'IAM. Conséquence pratique : révoquer la clé d'API coupe l'accès à la base, et les politiques IAM (avec leurs conditions, leçon 1) s'appliquent à la base comme à n'importe quelle API.
Pièges courants
Un cache qui devient la seule copie. Une file de tâches, des sessions de paiement, des données saisies : si elles ne vivent que dans Redis, la documentation de Scaleway vous a prévenu qu'elles peuvent disparaître. Le cache doit pouvoir être vidé à tout moment.
noeviction et la mémoire pleine. Avec la politique par défaut de Redis, un cache plein refuse toutes les écritures : l'erreur OOM command not allowed when used memory > 'maxmemory' remonte dans l'application. Réglez la politique, et donnez une durée de vie à chaque clé.
Des clés sans durée de vie. Avec volatile-lru, une clé sans durée de vie n'est jamais évincée ; si l'application en pose trop (un bogue qui oublie ex=), la mémoire se remplit de clés intouchables. Surveillez le nombre de clés sans expiration.
Le client qui ne connaît pas le cluster. Passer de cluster-size=1 à 3 change le protocole : les erreurs MOVED apparaissent avec un client ordinaire. Le mode se choisit avant d'écrire le code client.
TLS oublié, ou certificat non vérifié. tls-enabled=false fait circuler le mot de passe en clair ; ssl_cert_reqs=None côté client chiffre sans vérifier à qui l'on parle. Vérifiez le certificat.
Le démarrage à froid en production. Une API dont la base Serverless dort répond en cinq secondes à la première requête du matin, ce qui déclenche les délais d'attente du répartiteur ou de l'application. cpu-min=1 en production, ou une base managée classique.
Terraform qui stocke son état dans Serverless SQL. Les verrous consultatifs n'étant pas garantis, deux exécutions simultanées peuvent corrompre l'état. La page Known differences le dit explicitement ; le cours Terraform et OpenTofu : les fondamentaux stocke l'état ailleurs.
Un export qui contient des GRANT. Restaurer un export de la production dans Serverless SQL sans --no-owner --no-privileges échoue sur les commandes de rôles.
Sécurité
- Réseau privé pour Redis, et suppression de tout point d'accès public. Un Redis exposé sur Internet est l'une des cibles favorites des balayages automatiques ; les ACL par défaut d'un point d'accès public autorisent tout le monde, selon la documentation.
- TLS partout, avec vérification du certificat.
- Le seul utilisateur Redis a des droits fixés par Scaleway (
allkeyset les commandes du cluster), qu'on ne peut ni modifier ni compléter : il n'est pas possible de créer un utilisateur en lecture seule. Toute application qui a le mot de passe peut tout lire et tout effacer : ne partagez pas une instance entre applications qui ne se font pas confiance. - Pas de données personnelles sensibles dans le cache sans nécessité : elles y sont en clair en mémoire, et le cache échappe souvent aux revues de conformité.
- Serverless SQL est joignable depuis Internet : la protection repose sur IAM. Une clé d'application dédiée, avec expiration, un jeu de permissions limité aux données, et éventuellement une condition
request.ipsur l'adresse de sortie de la passerelle (leçon 1). - Les clés d'API sont désormais des mots de passe de base : elles se rangent dans Secret Manager, et leur rotation coupe les connexions qui les utilisent.
En production
Mesurer avant de cacher. Un cache se justifie par des chiffres : taux de requêtes identiques, temps de la requête en base, charge de la base. Après sa mise en place, le taux de réussite (hit ratio) du cache se suit dans Cockpit (leçon 14) : sous 80 %, la durée de vie ou les clés sont mal choisies.
Dimensionner Redis sur la mémoire. La taille d'un cache se calcule : nombre de clés multiplié par la taille moyenne des valeurs, plus la surcharge de Redis. Le type de nœud se choisit sur la mémoire, et l'on passe à un type plus grand (scw redis cluster migrate, quelques secondes de coupure en nœud seul d'après la documentation de montée de version, un nœud à la fois en haute disponibilité ou en cluster).
Préproduction serverless, production classique. C'est l'usage le plus sûr de Serverless SQL dans le contexte de Signalements : la préproduction dort la nuit et le week-end, la production garde une base managée avec haute disponibilité et réplica (leçon 3). Les différences de compatibilité imposent de tester l'application contre Serverless SQL avant de l'y déployer, et l'écart entre préproduction et production doit rester connu.
Chez Lyneko. Les applications de Lyneko qui tournent dans le cluster Kapsule utilisent un cache seulement là où une mesure l'a justifié ; un Redis managé partagé entre plusieurs applications n'est pas une bonne idée, faute d'utilisateurs distincts. Une instance par application, petite, coûte moins cher qu'un incident causé par une autre.
Quand choisir quoi.
| Besoin | Produit |
|---|---|
| Base de données principale de production | PostgreSQL managé (leçon 3) |
| Préproduction, prototype, outil interne peu utilisé | Serverless SQL, cpu-min=0 |
| Charge très irrégulière, tolérante à quelques secondes au réveil | Serverless SQL, cpu-min adapté |
| Cache de lectures répétées, compteurs, limitation de débit | Redis managé, nœud seul ou haute disponibilité |
| Sessions utilisateur | Redis, si les utilisateurs peuvent se reconnecter ; sinon la base principale |
| File de tâches fiable | Ni l'un ni l'autre : Messaging and Queuing (leçon 9) |
Exercices
1. Choisir la durée de vie (niveau 200). Pour chaque donnée de Signalements, proposez une stratégie de cache et une durée de vie, ou expliquez pourquoi elle ne doit pas être mise en cache : (a) la liste des 50 derniers signalements d'une métropole ; (b) le détail d'un signalement ; (c) le nombre de signalements ouverts affiché sur un tableau de bord ; (d) le mot de passe d'un agent ; (e) la liste des catégories de signalement, modifiée deux fois par an.
Solution
(a) Cache-aside, durée de vie courte (30 à 60 secondes) et invalidation à la création. (b) Cache-aside, durée de vie plus longue (quelques minutes) et invalidation à chaque modification du signalement : sinon un changement de statut reste invisible. (c) Durée de vie courte (une minute) sans invalidation : un tableau de bord tolère un léger retard, et invalider à chaque changement ferait recalculer en permanence. (d) Jamais : un secret n'a rien à faire dans un cache en clair en mémoire, partagé par toute l'application. (e) Durée de vie longue (une heure ou plus) avec invalidation à la modification, ou simplement un cache en mémoire dans chaque instance : la donnée est minuscule et presque immuable.
2. Calculer la mémoire (niveau 200). Signalements met en cache, pour 40 métropoles, la liste des 50 derniers signalements (environ 20 Ko par liste en JSON), le détail de chaque signalement consulté dans l'heure (environ 3 000 signalements, 2 Ko chacun), et un compteur de débit par clé partenaire (200 partenaires, deux fenêtres actives, quelques dizaines d'octets chacun). Estimez la mémoire nécessaire, avec un facteur de deux pour la surcharge de Redis, et choisissez un type de nœud.
Solution
Listes : 40 × 20 Ko = 800 Ko. Détails : 3 000 × 2 Ko = 6 Mo. Compteurs : 400 clés × environ 100 octets = 40 Ko. Total utile : moins de 7 Mo ; avec la surcharge, de l'ordre de 15 Mo. Le plus petit type de nœud suffit très largement en mémoire ; le choix entre types de développement et de production se fera sur la disponibilité et les performances réseau, pas sur la mémoire. Ce calcul montre qu'un cache est souvent bien plus petit qu'on ne l'imagine : ce sont les données chaudes, pas toute la base.
3. Un compteur partagé (niveau 200). Pourquoi la limitation de débit ne peut-elle pas être faite avec un dictionnaire Python dans chaque processus gunicorn, et que se passerait-il avec 2 instances de 2 processus chacune et une limite de 600 requêtes par minute ?
Solution
Chaque processus aurait son propre compteur. Avec 2 instances × 2 processus = 4 compteurs indépendants, et un répartiteur en tourniquet qui répartit les requêtes, un partenaire pourrait envoyer jusqu'à 4 × 600 = 2 400 requêtes par minute avant d'être limité, et ce nombre changerait à chaque mise à l'échelle du groupe. Un compteur dans Redis est partagé et atomique (INCR) : la limite vaut pour l'ensemble, quel que soit le nombre d'instances.
4. Préproduction serverless (niveau 200). La préproduction de Signalements est utilisée en moyenne 6 heures par semaine. Une base PostgreSQL managée du plus petit type est allumée en permanence. Que changez-vous, quelles vérifications faites-vous avant, et quel risque acceptez-vous ?
Solution
Passer la préproduction sur Serverless SQL avec cpu-min=0 : le calcul n'est facturé que pendant l'activité (environ 6 heures par semaine plus les cinq minutes de mise en veille après chaque usage), le stockage en permanence. Vérifications : charger un export anonymisé avec --no-owner --no-privileges ; lancer la suite de tests ; chercher dans le code les tables temporaires, LISTEN/NOTIFY, les verrous consultatifs (souvent utilisés par les outils de migration pour éviter deux migrations simultanées : vérifier l'outil de Signalements) ; adapter la connexion (identité IAM, sslmode=verify-full). Risques acceptés : quelques secondes de démarrage à froid à la première requête, et un écart de comportement entre préproduction et production, à garder documenté.
Récapitulatif
- Un cache garde des copies de données coûteuses ; le schéma cache-aside lit le cache puis la base ; l'invalidation se fait par expiration et à l'écriture. Le cache n'est jamais la source de vérité.
- Redis managé chez Scaleway : Redis 8.4 depuis février 2026, service zonal, trois modes (nœud seul, haute disponibilité asynchrone, cluster de 3 à 6 nœuds), un seul utilisateur aux droits fixes, TLS à activer, réseau privé à choisir à la création, pas de routage de VPC.
- La politique d'éviction (
volatile-lru,allkeys-lru) évite les erreurs de mémoire pleine ; chaque clé a une durée de vie. - La persistance par instantanés ne garantit pas la récupération : Scaleway réserve le produit au cache.
INCR, atomique, fait un compteur partagé pour la limitation de débit.- Serverless SQL Database : PostgreSQL qui descend à zéro après 5 minutes sans requête, démarrage à froid de quelques secondes, identifiants IAM, connexion TLS par Internet, sauvegarde quotidienne gardée 7 jours, région
fr-par. - Ses différences (pas de tables temporaires, verrous consultatifs non garantis, pas de
GRANT) excluent certains usages ; on teste avant. - Production : PostgreSQL managé ; préproduction : Serverless SQL ; cache : Redis ; file fiable : ni l'un ni l'autre.
Pour aller plus loin
- Les pages Key eviction et Redis persistence de la documentation de Redis, et la spécification du cluster Redis.
- La page Known differences between Serverless SQL Databases and PostgreSQL, à relire avant chaque nouvel usage.
- La leçon 8, pour ranger le mot de passe de Redis et les clés de Serverless SQL, et la leçon 9, pour les files de messages fiables que Redis ne doit pas remplacer.
Sources
- Scaleway, Managed Database for Redis : concepts, FAQ, Ensuring data persistence, Understanding default user permissions
- Scaleway, journal des changements : Redis v8.4 now supported, Redis v7.2.11 deprecated (19 février 2026)
- Scaleway, Serverless SQL Databases : overview, concepts, known differences, FAQ, How to manage backups
- Scaleway, Secure connection to Serverless SQL Databases (SSL/TLS)
- Redis, documentation : Key eviction, Redis persistence, Redis cluster specification
- Redis, Licenses (Redis 8 : RSALv2, SSPLv1 ou AGPLv3)
- Valkey, projet de la Linux Foundation
- PostgreSQL 17, documentation : Connections and Authentication, et libpq SSL support
- scaleway/scaleway-sdk-go, api/redis/v1 et api/serverless_sqldb/v1alpha1