Mis à jour ces 90 derniers jours 11 nouvelles · 7 révisées
Code de statut HTTP informatif défini par la RFC 8297 : pendant que le serveur prépare la vraie réponse (requête en base, rendu), il envoie d'abord un 103 contenant des en-têtes Link (preload, preconnect) pour que le navigateur commence à charger CSS, polices et scripts. Chrome le supporte depuis la version 103, uniquement sur HTTP/2 et HTTP/3 ; Cloudflare peut le générer automatiquement à partir des en-têtes Link de vos pages.
Le serveur du restaurant qui vous apporte pain et couverts dès la commande, sans attendre que le plat soit prêt en cuisine.
// Node.js >= 18 : res.writeEarlyHints (HTTP/2 côté proxy pour Chrome)
import http from 'node:http';
http.createServer(async (req, res) => {
res.writeEarlyHints({
link: [
'</styles/app.css>; rel=preload; as=style',
'</fonts/inter.woff2>; rel=preload; as=font; crossorigin',
'<https://api.example.com>; rel=preconnect',
],
}); // 103 part immédiatement
const html = await renderPage(req); // travail lent (BDD, SSR)
res.writeHead(200, { 'content-type': 'text/html' });
res.end(html); // 200 final
}).listen(3000);Cas d'usage : Pages rendues côté serveur avec un TTFB de plusieurs centaines de millisecondes : les ressources critiques se chargent pendant l'attente.
Authentification multi-facteurs combinant quelque chose que l'utilisateur sait (mot de passe), possède (téléphone/clé) ou est (biométrie). Réduit drastiquement les compromissions.
Entrer dans un coffre-fort de banque avec une clé ET un code : voler l'un sans l'autre est inutile.
import { authenticator } from 'otplib';
const secret = authenticator.generateSecret();
const qrUrl = authenticator.keyuri(user.email, 'MyApp', secret);
// Verification
const isValid = authenticator.verify({
token: userInput, secret: user.totpSecret
});Cas d'usage : Ajouter une couche de sécurité obligatoire pour les comptes admin et les opérations sensibles.
Service SaaS de recherche instantanée avec typo-tolérance, facettes et analytics intégrés. Offre des widgets UI prêts à l'emploi (InstantSearch).
Un moteur de recherche Google clé en main pour votre propre site, avec résultats en moins de 50ms.
import algoliasearch from 'algoliasearch';
const client = algoliasearch('APP_ID', 'SEARCH_KEY');
const index = client.initIndex('products');
const { hits } = await index.search('iphone', {
filters: 'price < 1000',
hitsPerPage: 20,
});Cas d'usage : Ajouter rapidement une recherche performante sur un site e-commerce ou une documentation.
Bonnes pratiques de gestion des clés API : génération sécurisée, stockage hashé côté serveur, rotation régulière, scoping des permissions et révocation.
Des clés de voiture numérotées avec un registre : on sait qui a quelle clé, on peut la désactiver à distance.
const apiKey = `sk_live_${crypto.randomBytes(32).toString('hex')}`;
// Store only hash in DB
const hash = crypto.createHash('sha256').update(apiKey).digest('hex');
await db.insert({ hash, userId, permissions: ['read'], expiresAt });Cas d'usage : Fournir un accès programmatique à votre API avec traçabilité et contrôle granulaire.
Ensemble de techniques pour empêcher les attaques par force brute sur l'authentification : lockout progressif, CAPTCHA, délai exponentiel entre les tentatives.
Un coffre-fort qui ajoute 10 secondes d'attente supplémentaires après chaque mauvais code, rendant le crochetage impraticable.
const attempts = await getLoginAttempts(email);
if (attempts > 5) {
const delay = Math.pow(2, attempts - 5) * 1000;
await sleep(delay); // Exponential backoff
}
if (attempts > 10) {
requireCaptcha(req);
}Cas d'usage : Protéger les formulaires de login et de reset de mot de passe contre les attaques automatisées.
Réseau de serveurs géographiquement distribués qui cache et sert le contenu statique au plus près des utilisateurs. Réduit la latence et décharge le serveur d'origine.
Des boulangeries de quartier qui stockent le pain cuit à la boulangerie centrale : plus besoin de traverser la ville.
// Next.js with CDN headers
export async function GET() {
return new Response(data, {
headers: {
'Cache-Control': 'public, s-maxage=3600, stale-while-revalidate=86400',
},
});
}Cas d'usage : Servir les assets statiques, images et API réponses cachées avec latence < 50ms mondiale.
Workflow lancé depuis un autre Workflow parent dans Temporal. Permet la décomposition de processus complexes et l'isolation des échecs.
Un manager qui délègué une sous-tâche à un employé tout en continuant son propre travail.
async function parentWorkflow(orders) {
const handles = orders.map(order =>
startChild(processOrderWorkflow, { args: [order] })
);
return Promise.all(handles.map(h => h.result()));
}Cas d'usage : Traiter en parallèle plusieurs sous-processus indépendants tout en gardant un contrôle centralisé.
Deux approches de coordination de services. Orchestration : un chef centralisé dirige (Temporal). Chorégraphie : chaque service réagit aux événements des autres (event-driven).
Orchestre symphonique (chef d'orchestre dirigeant chaque musicien) vs danse de salon (chaque danseur réagit aux mouvements du partenaire).
// Orchestration (centralized)
await paymentService.charge(order);
await inventoryService.reserve(order);
await shippingService.ship(order);
// Choreography (event-driven)
eventBus.emit('order.created', order);
// Each service listens and reacts independentlyCas d'usage : Choisir orchestration pour les workflows critiques avec compensation, chorégraphie pour le découplage maximal.
Algorithmes de compression HTTP réduisant la taille des transferts. Brotli offre 15-20% de compression en plus que gzip et est supporté par tous les navigateurs modernes.
Aspirer l'air d'un sac sous vide avant de l'envoyer par la poste pour réduire les frais de port.
// Express with compression
import compression from 'compression';
app.use(compression({ level: 6 }));
// Nginx config
gzip on;
brotli on;
brotli_types text/html application/javascript text/css;Cas d'usage : Réduire de 60-80% la taille des transferts HTTP pour les fichiers texte (JS, CSS, HTML, JSON).
En-tête HTTP qui restreint les sources autorisées pour scripts, styles, images et connexions : première défense contre les XSS. La spécification CSP Level 3 reste un Working Draft du W3C (dernière version du 13 août 2026) mais ses apports clés, 'strict-dynamic' et les nonces, sont largement implémentés. Elle s'accompagne des Trusted Types (require-trusted-types-for), disponibles dans tous les navigateurs majeurs depuis février 2026.
Une liste blanche à l'entrée d'un club VIP : seules les sources approuvées peuvent entrer et s'exécuter.
// CSP « stricte » niveau 3 : nonce + strict-dynamic
Content-Security-Policy:
default-src 'self';
script-src 'nonce-r4nd0m' 'strict-dynamic';
object-src 'none';
base-uri 'none';
require-trusted-types-for 'script'; // Trusted Types
trusted-types app-policy;
// Le nonce change à chaque réponse ; les scripts qu'il charge
// dynamiquement héritent de la confiance (strict-dynamic).Cas d'usage : Empêcher l'exécution de scripts malicieux injectés dans la page (XSS, injection de publicités).
Mécanisme Temporal qui termine un Workflow et en démarre un nouveau avec un historique frais. Évite la croissance illimitée de l'historique d'événements.
Commencer un nouveau carnet quand l'ancien est plein, en notant juste le résumé de la dernière page.
async function pollingWorkflow(state) {
for (let i = 0; i < 100; i++) {
state = await pollExternal(state);
}
await continueAsNew(state);
}Cas d'usage : Maintenir des Workflows de longue durée (polling, monitoring) sans dépasser la limite d'historique.
Les attributs de sécurité des cookies : httpOnly empêche l'accès JavaScript (anti-XSS), secure exige HTTPS, sameSite protège contre le CSRF.
Un coffre-fort avec trois serrures : une contre le vol numérique, une contre l'espionnage réseau, une contre la tromperie.
res.cookie('session', token, {
httpOnly: true, // No JS access
secure: true, // HTTPS only
sameSite: 'lax', // CSRF protection
maxAge: 3600000, // 1 hour
path: '/',
});Cas d'usage : Stocker des tokens d'authentification de manière sécurisée dans le navigateur.
Trois métriques Google d'expérience utilisateur : LCP (affichage du plus grand élément), INP (réactivité à toutes les interactions de la visite) et CLS (stabilité visuelle). INP a officiellement remplacé FID comme Core Web Vital le 12 mars 2024 ; le seuil « bon » est un INP sous 200 ms pour au moins 75 % des visites.
Les 3 notes d'un restaurant : rapidité du service (LCP), réactivité du serveur (INP), stabilité de la table (CLS).
// Mesure terrain (RUM) avec la librairie web-vitals
import { onLCP, onINP, onCLS } from 'web-vitals';
onLCP(({ value }) => analytics.send('LCP', value));
onINP(({ value }) => analytics.send('INP', value)); // remplace FID depuis le 12/03/2024
onCLS(({ value }) => analytics.send('CLS', value));
// Seuils « bon » : LCP < 2,5 s · INP < 200 ms · CLS < 0,1Cas d'usage : Monitorer et optimiser l'UX mesurable pour améliorer le SEO et la satisfaction utilisateur.
Mécanisme de sécurité navigateur qui bloque les requêtes cross-origin. Les requêtes non-simples déclenchent un preflight OPTIONS pour vérifier les permissions du serveur.
Avant de livrer un colis international, le douanier appelle le destinataire pour vérifier qu'il attend bien ce paquet.
import cors from 'cors';
app.use(cors({
origin: 'https://myapp.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
credentials: true,
maxAge: 86400, // Cache preflight 24h
}));Cas d'usage : Configurer une API backend pour accepter les requêtes du frontend déployé sur un autre domaine.
Exécution de code côté serveur au plus près de l'utilisateur sur un réseau distribué de points de présence (PoP). Réduit la latence de 100-300ms à 10-50ms.
Des guichets de banque dans chaque quartier au lieu d'un seul siège en centre-ville.
// Cloudflare Worker
export default {
async fetch(request) {
const country = request.cf?.country;
const cached = await caches.default.match(request);
if (cached) return cached;
const response = await fetch(request);
return response;
},
};Cas d'usage : Personnalisation géographique, auth validation, A/B testing et cache API au plus près des utilisateurs.
Moteur de recherche distribué basé sur Lucene, optimisé pour la recherche full-text, l'analyse de logs et l'agrégation de données à grande échelle.
Un bibliothécaire surpuissant qui retrouve n'importe quel livre en millisecondes parmi des millions.
const results = await client.search({
index: 'products',
body: {
query: { multi_match: {
query: 'chaussure running',
fields: ['name^3', 'description'],
fuzziness: 'AUTO'
}}
}
});Cas d'usage : Recherche produit e-commerce, analyse de logs (ELK stack), moteur de suggestions.
Frameworks pour créer des emails HTML responsives. MJML utilise un langage de balisage dédié, React Émail utilise des composants React transpilés en HTML compatible email.
Un moule à gâteau pour emails : vous choisissez la forme, le contenu s'adapte automatiquement à tous les fours (clients email).
// React Email component
import { Html, Button, Text } from '@react-email/components';
export function WelcomeEmail({ name, url }) {
return (
<Html>
<Text>Bienvenue {name} !</Text>
<Button href={url}>Confirmer</Button>
</Html>
);
}Cas d'usage : Créer des emails professionnels responsives compatibles Outlook, Gmail et Apple Mail.
Système de filtrage dynamique qui affiche les catégories disponibles avec leur nombre de résultats, permettant un affinage progressif de la recherche.
Les filtres sur un site immobilier (prix, surface, ville) qui se mettent à jour selon les résultats disponibles.
const results = await index.search('laptop', {
facets: ['brand', 'price_range', 'ram'],
});
// Returns: { brand: { Apple: 42, Dell: 38 }, ... }Cas d'usage : Navigation produit e-commerce avec filtres dynamiques (marque, prix, taille, couleur).
Moment où le navigateur affiche le premier contenu visible (texte, image, SVG). Indique quand l'utilisateur perçoit que la page commence à charger.
Le moment où la première image apparaît quand on allume une vieille télévision à tube.
// Performance Observer for FCP
new PerformanceObserver((entries) => {
const fcp = entries.getEntriesByName('first-contentful-paint')[0];
console.log(`FCP: ${fcp.startTime}ms`); // Target: < 1.8s
}).observe({ type: 'paint', buffered: true });Cas d'usage : Mesurer le temps de perception initial et identifier les blocages de rendu (CSS/JS bloquants).
Modèle mathématique avec un nombre fini d'états, de transitions entre ces états et d'événements déclencheurs. Le système ne peut être que dans un seul état à la fois.
Un feu tricolore : vert, orange ou rouge, jamais deux à la fois, et les transitions suivent un ordre strict.
// Simple FSM
const transitions = {
green: { TIMER: 'yellow' },
yellow: { TIMER: 'red' },
red: { TIMER: 'green' },
};
function next(state, event) {
return transitions[state]?.[event] ?? state;
}Cas d'usage : Modéliser tout processus séquentiel avec des règles de transition strictes (UI, protocoles, workflows).
Techniques d'optimisation des polices web : subsetting (garder seulement les caractères utilisés), font-display:swap, preload et formats modernes (woff2).
Ne mettre dans sa valise que les vêtements qu'on va porter au lieu d'emporter toute la garde-robe.
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-latin.woff2') format('woff2');
font-display: swap;
unicode-range: U+0000-00FF; /* Latin subset only */
}
/* Preload in HTML */
/* <link rel="preload" href="/fonts/inter-latin.woff2" as="font"> */Cas d'usage : Réduire le FOUT/FOIT et le poids des polices pour améliorer le LCP et le CLS.
Technique de recherche qui analyse le contenu textuel complet des documents, avec tokenisation, stemming et scoring de pertinence, contrairement au simple LIKE SQL.
Chercher un livre non par son titre exact mais par les idées qu'il contient, même formulées différemment.
-- PostgreSQL full-text search
SELECT title, ts_rank(search_vector, query) AS rank
FROM articles,
to_tsquery('french', 'développement & web') AS query
WHERE search_vector @@ query
ORDER BY rank DESC;Cas d'usage : Recherche dans des articles, documentation ou descriptions produits avec pertinence linguistique.
Recherche approximative tolérant les fautes de frappe en calculant la distance d'édition (Levenshtein) entre le terme saisi et les termes indexés.
Un ami qui comprend 'javscript' quand vous vouliez dire 'javascript' grâce au contexte.
// Meilisearch fuzzy by default
const results = await index.search('javscrpt');
// Returns: 'JavaScript' (1 typo tolerance)
// Elasticsearch
{ query: { fuzzy: { name: { value: 'javscrpt', fuzziness: 2 } } } }Cas d'usage : Offrir une expérience de recherche indulgente sur un site e-commerce ou une documentation.
Architecture où plusieurs services GraphQL indépendants (sous-graphes, un par domaine : utilisateurs, produits, commandes) sont composés en un unique schéma (supergraphe) servi par un routeur qui planifie et distribue chaque requête. Apollo Fédération 2 assouplit la propriété partagée des types et compose un supergraphe rétrocompatible avec les sous-graphes v1 ; Apollo Router en est l'exécuteur de référence.
Un guichet unique de mairie : vous déposez un seul formulaire, l'agent d'accueil le découpe et interroge l'état civil, l'urbanisme et la voirie, puis vous rend une réponse assemblée.
# Sous-graphe « avis » qui étend le type Product du sous-graphe « produits »
extend schema @link(url: "https://specs.apollo.dev/federation/v2.3",
import: ["@key", "@shareable"])
type Product @key(fields: "id") {
id: ID!
reviews: [Review!]! # résolu ici, le reste vient de « produits »
}
type Review { id: ID!, rating: Int!, body: String }
# Le routeur reçoit { product(id) { name reviews { rating } } }
# et appelle les deux sous-graphes, puis fusionne par @key.Cas d'usage : Plusieurs équipes possèdent chacune leur domaine et veulent une API GraphQL unifiée pour les fronts, sans monolithe de schéma.
Middleware Express qui configure automatiquement une dizaine d'en-têtes de sécurité HTTP (CSP, HSTS, X-Frame-Options, etc.) avec des valeurs saines par défaut.
Un casque de protection tout-en-un qui protège la tête sous tous les angles sans effort.
import helmet from 'helmet';
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "'nonce-abc'"],
},
},
}));Cas d'usage : Appliquer les bonnes pratiques de sécurité HTTP en une seule ligne sur toute app Express.
Version majeure du protocole HTTP avec multiplexage (plusieurs requêtes sur une connexion), compression des headers (HPACK) et server push. Élimine le besoin de concaténation.
Une autoroute à plusieurs voies au lieu d'une route à voie unique avec feu de circulation.
// Nginx HTTP/2 config
server {
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
}
// Node.js
import http2 from 'node:http2';
const server = http2.createSecureServer({ cert, key });Cas d'usage : Améliorer la performance de chargement en parallélisant les requêtes sans overhead de connexion.
Version d'HTTP construite sur QUIC (UDP) plutôt que TCP : plus de blocage en tête de ligne entre flux, reprise de connexion rapide, meilleure tenue sur mobile. Côté serveur, nginx fournit le module ngx_http_v3_module depuis la version 1.25.0, toujours marqué « expérimental » dans sa documentation officielle et à compiler avec --with-http_v3_module ; Cloudflare et Caddy l'activent nativement.
Passer de la route (TCP) à l'avion (QUIC) : plus de bouchons, connexion plus rapide et changement de réseau fluide.
# nginx >= 1.25.0 compilé avec --with-http_v3_module (statut expérimental)
server {
listen 443 quic reuseport; # HTTP/3 (UDP)
listen 443 ssl; # HTTP/1.1 + HTTP/2 (TCP)
http2 on;
http3 on;
ssl_certificate /etc/ssl/site.crt;
ssl_certificate_key /etc/ssl/site.key;
add_header Alt-Svc 'h3=":443"; ma=86400'; # annonce h3 aux clients
}
# Ne pas oublier : ouvrir 443/UDP sur le pare-feuCas d'usage : Améliorer la latence sur les connexions mobiles instables et les réseaux à forte perte de paquets.
Protocole de chiffrement des communications web utilisant TLS. Garantit la confidentialité, l'intégrité et l'authenticité des échanges entre client et serveur.
Une enveloppe scellée et signée : personne ne peut lire le contenu ni le modifier en chemin.
// Force HTTPS redirect (Express)
app.use((req, res, next) => {
if (req.header('x-forwarded-proto') !== 'https') {
return res.redirect(301, `https://${req.hostname}${req.url}`);
}
next();
});Cas d'usage : Obligatoire pour toute application en production, requis pour les cookies Secure et HTTP/2.
Conversion des images vers des formats modernes (WebP, AVIF) avec redimensionnement responsive. AVIF offre 50% de compression en plus que JPEG à qualité égale.
Compresser une valise avec des sacs sous vide : même contenu, moitié de place.
import sharp from 'sharp';
await sharp(inputBuffer)
.resize(800, 600, { fit: 'inside' })
.avif({ quality: 60 })
.toFile('output.avif');
// Fallback chain: AVIF > WebP > JPEGCas d'usage : Réduire le poids des images de 60-80% pour améliorer le LCP et la bande passante.
Système de notifications intégré à l'application (cloche, badge, toasts) avec centre de notifications persistant. Utilise souvent WebSocket ou SSE pour le temps réel.
La boîte de réception interne d'un bureau avec un voyant lumineux qui s'allume quand un nouveau message arrive.
// Notification center pattern
const [notifications, setNotifications] = useState([]);
useEffect(() => {
const es = new EventSource('/api/notifications/stream');
es.onmessage = (e) => {
setNotifications(prev => [JSON.parse(e.data), ...prev]);
};
return () => es.close();
}, []);Cas d'usage : Informer l'utilisateur d'événements (mentions, mises à jour, tâches) sans quitter l'application.
Packages partagés au sein d'un monorepo sans publication sur NPM. Référencés via le protocole workspace, ils permettent le partage de code typé entre applications.
Des recettes maison partagées entre restaurants du même groupe, jamais publiées dans un livre de cuisine.
// packages/ui/package.json
{ "name": "@myorg/ui", "main": "./src/index.ts" }
// apps/web/package.json
{ "dependencies": { "@myorg/ui": "workspace:*" } }
// Usage
import { Button } from '@myorg/ui';Cas d'usage : Partager des composants UI, utils ou types entre le frontend et le backend d'un monorepo.
Structure de données qui associe chaque terme à la liste des documents le contenant. Fondement de tous les moteurs de recherche full-text pour des requêtes en O(1).
L'index alphabétique à la fin d'un livre : au lieu de lire tout le livre, on cherche le mot et on trouve les pages.
// Simplified inverted index
const index = {
'javascript': [docId1, docId3, docId7],
'react': [docId1, docId2],
'node': [docId3, docId5, docId7],
};Cas d'usage : Comprendre le fonctionnement interne d'Elasticsearch, Meilisearch et des moteurs de recherche.
Token auto-contenu composé de 3 parties (header, payload, signature) encodé en Base64. Permet l'authentification stateless sans interroger la base de données à chaque requête.
Un badge visiteur avec photo, nom et tampon de sécurité : toutes les infos sont sur le badge, pas besoin de vérifier un registre.
import jwt from 'jsonwebtoken';
const accessToken = jwt.sign(
{ userId: user.id, role: 'admin' },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);Cas d'usage : Authentification API stateless avec access token court (15min) et refresh token long (7j).
Stratégie où le refresh token est à usage unique : chaque utilisation génère une nouvelle paire access/refresh. Détecte le vol de token par réutilisation.
Un ticket de vestiaire à usage unique : si quelqu'un l'a déjà utilisé, le vestiaire sait qu'il y a fraude.
async function rotateTokens(refreshToken) {
const stored = await db.findToken(refreshToken);
if (stored.used) {
await db.revokeFamily(stored.familyId); // Compromis!
throw new Error('Token reuse detected');
}
await db.markUsed(refreshToken);
return generateTokenPair(stored.userId, stored.familyId);
}Cas d'usage : Sécuriser les sessions longue durée en détectant automatiquement le vol de refresh token.
Outil historique de gestion de monorepos JS pour le versioning et la publication de packages NPM. Désormais maintenu par Nx avec cache et graphe de tâches intégrés.
Un éditeur de livres qui gère les versions et la publication coordonnée de toute une collection.
// lerna.json
{
"version": "independent",
"npmClient": "pnpm",
"command": {
"publish": { "conventionalCommits": true }
}
}Cas d'usage : Publier et versionner des packages NPM interdépendants depuis un monorepo avec changelog automatique.
Outil Google d'audit automatisé mesurant performance, accessibilité, SEO et bonnes pratiques d'une page web. Disponible dans Chrome DevTools et en CI.
Un contrôle technique automobile qui inspecte tous les aspects de votre véhicule et donne une note.
// Lighthouse CI
npx lhci autorun --collect.url=https://myapp.com
// lighthouse.config.js
{ ci: { assert: {
assertions: {
'categories:performance': ['error', { minScore: 0.9 }],
'categories:accessibility': ['warn', { minScore: 0.95 }],
}
}}}Cas d'usage : Auditer automatiquement les pages en CI pour détecter les régressions de performance et accessibilité.
Technique où le client envoie une requête HTTP et le serveur la garde ouverte jusqu'à avoir de nouvelles données. Simule du temps réel sans WebSocket.
Appeler un restaurant pour demander si une table est libre et rester en ligne jusqu'à ce qu'une se libère.
async function longPoll() {
const res = await fetch('/api/updates?timeout=30000');
const data = await res.json();
processUpdate(data);
longPoll(); // Immediately reconnect
}Cas d'usage : Fallback temps réel quand WebSocket ou SSE ne sont pas disponibles (firewalls, proxies).
Moteur de recherche open-source ultra-rapide et simple à configurer. Alternative à Algolia avec typo-tolérance, filtres et tri, déployable on-premise.
Un Algolia gratuit que vous pouvez héberger chez vous, aussi rapide mais sans la facture SaaS.
import { MeiliSearch } from 'meilisearch';
const client = new MeiliSearch({ host: 'http://localhost:7700' });
await client.index('movies').addDocuments(movies);
const results = await client.index('movies').search('avenger', {
filter: ['year > 2015'],
});Cas d'usage : Recherche instantanée sur un projet avec contraintes budget/données sensibles nécessitant du self-hosted.
Protocole de push temps réel basé sur SSE avec un hub central. Le serveur publie des updates vers le hub qui les distribue aux clients abonnés via SSE.
Un bureau de poste central qui reçoit les lettres des expéditeurs et les distribue aux boîtes aux lettres des abonnés.
// Publish from server
await fetch('https://hub.example.com/.well-known/mercure', {
method: 'POST',
headers: { Authorization: `Bearer ${jwt}` },
body: new URLSearchParams({
topic: '/orders/42', data: JSON.stringify(order)
}),
});Cas d'usage : Push temps réel dans un écosystème Symfony/API Platform sans gérer l'infrastructure WebSocket.
Technique de découpage d'un fichier volumineux en plusieurs parties uploadées en parallèle. Permet la reprise en cas d'erreur et optimise le débit réseau.
Déménager en envoyant les cartons par plusieurs camions en parallèle plutôt qu'un seul gros camion.
const upload = new Upload({
client: s3,
params: {
Bucket: 'videos', Key: 'movie.mp4', Body: fileStream,
},
partSize: 10 * 1024 * 1024, // 10MB parts
leavePartsOnError: false,
});
await upload.done();Cas d'usage : Upload de fichiers volumineux (vidéos, datasets) avec barre de progression et reprise sur erreur.
Framework de monorepo avec graphe de dépendances intelligent, cache distribué et générateurs de code. Supporte React, Angular, Node et plus avec des plugins dédiés.
Un architecte de chantier qui connaît toutes les dépendances entre bâtiments et ne rénove que ce qui est impacté.
// nx.json - affected commands
npx nx affected --target=test // Only test changed
npx nx affected --target=build // Only build changed
npx nx graph // Visualize dependency graphCas d'usage : Gérer un monorepo d'entreprise multi-frameworks avec des dizaines de projets interdépendants.
Révision d'OAuth 2.0 qui consolide dans une seule spécification les bonnes pratiques de sécurité accumulées depuis 2012. Encore un brouillon IETF (draft-ietf-oauth-v2-1-15 du 2 mars 2026), il rend PKCE obligatoire pour le flux Authorization Code, supprime les flux Implicit et Resource Owner Password, exige la comparaison exacte des redirect_uri, interdit les jetons bearer dans les paramètrès d'URL et impose rotation ou liaison des refresh tokens. Le protocole MCP l'a adopté pour son autorisation.
Le code de la route réédité : pas de nouvelles routes, mais les mauvaises habitudes tolérées (rouler sans ceinture) deviennent des infractions.
// Client OAuth 2.1 : Authorization Code + PKCE, même pour un backend
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = base64url(await sha256(verifier));
const authorizeUrl = new URL('https://auth.example.com/authorize');
authorizeUrl.search = new URLSearchParams({
response_type: 'code', // plus de response_type=token (Implicit)
client_id: CLIENT_ID,
redirect_uri: 'https://app.example.com/cb', // comparée à l'octet près
code_challenge: challenge,
code_challenge_method: 'S256',
state: csrfToken,
scope: 'openid profile',
});
// Échange du code : POST /token avec code_verifier, jamais dans l'URL.Cas d'usage : Toute nouvelle intégration OAuth (SPA, mobile, backend, agents MCP) : appliquer 2.1 dès aujourd'hui évite une migration future.
Cadre d'autorisation déléguée : une application accède aux ressources d'un utilisateur sans connaître son mot de passe. OAuth 2.1 (brouillon IETF draft-ietf-oauth-v2-1-15 du 2 mars 2026) consolide les bonnes pratiques : PKCE obligatoire pour le flux Authorization Code, suppression des flux Implicit et Password, comparaison exacte des redirect_uri, plus de jeton bearer dans l'URL.
Donner un passe limité au plombier pour accéder à la salle de bain sans lui donner les clés de toute la maison.
// Authorization Code flow (redirect)
const authUrl = `https://auth.example.com/authorize
?response_type=code
&client_id=${CLIENT_ID}
&redirect_uri=${REDIRECT}
&scope=read:profile
&state=${csrfToken}`;Cas d'usage : Permettre le 'Login with Google/GitHub' ou accéder aux APIs tierces au nom de l'utilisateur.
Extension d'OAuth 2.0 (Proof Key for Code Exchange, RFC 7636) qui protège le flux Authorization Code contre l'interception du code : le client envoie un code_challenge (SHA-256 d'un code_vérifier aléatoire) puis prouve qu'il détient le vérifier à l'échange du jeton. OAuth 2.1 rend PKCE obligatoire pour tous les clients, publics comme confidentiels.
Envoyer un cadenas ouvert avec la demande, puis prouver qu'on a la clé en l'ouvrant lors de l'échange.
const verifier = generateRandomString(128);
const challenge = base64url(sha256(verifier));
// Step 1: Send challenge
`&code_challenge=${challenge}&code_challenge_method=S256`
// Step 2: Send verifier to get token
`&code_verifier=${verifier}`Cas d'usage : Sécuriser le flow OAuth2 dans les SPA et apps mobiles qui ne peuvent pas garder un client_secret.
Format standard de description d'API HTTP (ex-Swagger), géré par l'OpenAPI Initiative sous la Linux Foundation. La version 3.1 aligne les schémas sur JSON Schema 2020-12 ; la version 3.2, annoncée le 23 septembre 2025, ajoute sans rupture les tags structurés (résumé, parent, type), un support de première classe des réponses en flux (streaming), des méthodes HTTP arbitraires et le flux OAuth 2 « device ». Le document sert à générer documentation, clients typés, mocks et tests de contrat.
Le plan coté d'un bâtiment : électriciens, plombiers et clients lisent le même document, chacun y trouve ce qu'il doit brancher.
openapi: 3.2.0
info: { title: API Commandes, version: 1.4.0 }
tags:
- name: commandes
summary: Cycle de vie des commandes # tag structuré (3.2)
paths:
/orders/{id}:
get:
tags: [commandes]
parameters: [{ name: id, in: path, required: true, schema: { type: string } }]
responses:
'200':
description: Commande trouvée
content: { application/json: { schema: { $ref: '#/components/schemas/Order' } } }
'404': { description: Inconnue }Cas d'usage : API publique ou partagée entre équipes/langages : contrat unique, SDK générés, validation des requêtes et mocks côté front.
Couche d'identité construite sur OAuth2 qui ajoute l'authentification. Retourne un ID Token (JWT) contenant les informations de l'utilisateur en plus de l'access token.
OAuth2 dit 'cette personne a le droit d'entrer', OpenID Connect ajoute 'et voici sa carte d'identité'.
// ID Token decoded payload
{
"sub": "user-123",
"name": "Alice Martin",
"email": "[email protected]",
"iss": "https://auth.example.com",
"aud": "my-app-client-id",
"exp": 1700000000
}Cas d'usage : Implémenter un SSO (Single Sign-On) d'entreprise avec identification fiable de l'utilisateur.
Classement des dix risques de sécurité applicative les plus critiques, publié par l'OWASP. L'édition 2025 remplace celle de 2021 : A01 Broken Access Control (qui absorbe SSRF), A02 Security Misconfiguration, A03 Software Supply Chain Failures (nouveau), A04 Cryptographic Failures, A05 Injection, A06 Insecure Design, A07 Authentication Failures, A08 Software or Data Integrity Failures, A09 Security Logging and Alerting Failures, A10 Mishandling of Exceptional Conditions (nouveau).
Le top 10 des erreurs les plus courantes au code de la route : les connaître évite 90% des accidents.
// A05:2025 Injection – requête paramétrée
const user = await db.query(
'SELECT * FROM users WHERE id = $1', // jamais de concaténation
[userId]
);
// A10:2025 Mishandling of Exceptional Conditions – échouer proprement
try { await pay(order); }
catch (err) {
logger.error({ err, orderId: order.id }); // A09 : journaliser + alerter
throw new PaymentError('Paiement refusé'); // pas de fuite de détails
}Cas d'usage : Grille de lecture obligatoire en revue de code ou en audit ; l'entrée A03:2025 impose de regarder les dépendances, les pipelines CI et les artefacts (SBOM, signatures).
PASETO (Platform-Agnostic Security Tokens) est un format de jeton conçu pour éliminer les pièges de JWT : pas d'en-tête « alg » négociable, donc aucune attaque par confusion d'algorithme ou « alg: none ». Chaque jeton porte sa version et son but : v4.local est chiffré et authentifié (XChaCha20-Poly1305, clé symétrique), v4.public est signé (Ed25519) et lisible. On perd l'interopérabilité universelle de JWT et de ses profils (OpenID Connect).
JWT est une enveloppe où l'expéditeur choisit lui-même le type de cachet, parfois « aucun » ; PASETO impose un seul cachet infalsifiable par version.
import { V4 } from 'paseto';
// Signature (v4.public) : payload lisible, non modifiable
const { secretKey, publicKey } = await V4.generateKey('public');
const token = await V4.sign(
{ sub: 'user_42', role: 'admin' },
secretKey,
{ expiresIn: '15m', audience: 'api', issuer: 'auth' },
);
// v4.public.eyJzdWIiOiJ1c2VyXzQyIi... (version + but dans le préfixe)
const payload = await V4.verify(token, publicKey, { audience: 'api' });
// Aucun paramètre « algorithms » à sécuriser : il n'y a qu'Ed25519.Cas d'usage : Jetons internes entre vos propres services ou sessions stateless, quand vous maîtrisez les deux bouts et voulez supprimer une classe entière de vulnérabilités.
Standard d'authentification sans mot de passe utilisant la cryptographie asymétrique. La clé privée reste sur l'appareil de l'utilisateur, seule la clé publique est stockée côté serveur.
Un verrou qui ne reconnaît que votre empreinte digitale : impossible à copier, rien à retenir.
const credential = await navigator.credentials.create({
publicKey: {
challenge: serverChallenge,
rp: { name: 'MyApp' },
user: { id: userId, name: email, displayName: name },
pubKeyCredParams: [{ alg: -7, type: 'public-key' }],
}
});Cas d'usage : Remplacer les mots de passe par une authentification résistante au phishing sur mobile et desktop.
Limites maximales définies pour les métriques de performance (taille JS < 200KB, LCP < 2.5s). Bloque le build ou alerte quand les budgets sont dépassés.
Un budget financier pour les courses : si vous dépassez, vous devez retirer un article avant de passer en caisse.
// bundlesize config or CI check
{
"budgets": [
{ "path": "dist/*.js", "maxSize": "200kB" },
{ "path": "dist/*.css", "maxSize": "50kB" },
{ "metric": "LCP", "max": 2500 }
]
}Cas d'usage : Empêcher la régression de performance en intégrant des garde-fous dans le pipeline CI/CD.
Fonctionnalité native de pnpm pour gérer un monorepo avec symlinks et content-addressable store. Économise l'espace disque en partageant les dépendances identiques.
Une bibliothèque partagée où chaque bureau a un raccourci vers le livre au lieu d'une copie complète.
# pnpm-workspace.yaml
packages:
- 'apps/*'
- 'packages/*'
# Using workspace protocol
{ "dependencies": { "@myorg/ui": "workspace:*" } }Cas d'usage : Structurer un monorepo avec gestion efficace des dépendances partagées et résolution rapide.
URL temporaire signée cryptographiquement qui donne un accès limité dans le temps à un objet S3. Permet l'upload/download direct sans exposer les credentials.
Un ticket de vestiaire avec date d'expiration : il donne accès à un seul casier pendant un temps limité.
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
const url = await getSignedUrl(s3, new PutObjectCommand({
Bucket: 'uploads',
Key: `docs/${fileId}`,
ContentType: 'application/pdf',
}), { expiresIn: 300 }); // 5 minCas d'usage : Permettre l'upload direct du navigateur vers S3 sans passer par votre serveur backend.
Messages envoyés depuis un serveur vers l'appareil de l'utilisateur via APNs (Apple) ou FCM (Google), même quand l'application est fermée. Requiert un Service Worker sur le web.
Un facteur qui sonne à votre porte pour livrer un message urgent, même si vous n'attendiez rien.
// Web Push API
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: VAPID_PUBLIC_KEY,
});
// Server-side
await webpush.sendNotification(subscription, JSON.stringify({
title: 'New message', body: 'Alice sent you a photo',
}));Cas d'usage : Réengager les utilisateurs avec des alertes pertinentes (messages, commandes, promotions ciblées).
Mécanisme qui limite le nombre de requêtes qu'un client peut faire dans une fenêtre de temps. Protège contre les abus, DDoS et scraping.
Un distributeur de tickets qui ne donne qu'un ticket par minute par personne pour éviter la bousculade.
import rateLimit from 'express-rate-limit';
app.use('/api/', rateLimit({
windowMs: 15 * 60 * 1000, // 15 min
max: 100, // 100 requests per window
standardHeaders: true,
message: 'Too many requests',
}));Cas d'usage : Protéger les endpoints d'authentification et les API publiques contre les abus automatisés.
Directives HTML (preload, prefetch, preconnect, dns-prefetch) qui informent le navigateur des ressources à charger en priorité ou à préparer en avance.
Commander l'entrée et le plat en même temps au restaurant pour que le plat arrive plus vite après l'entrée.
<!-- Critical resource -->
<link rel="preload" href="/fonts/inter.woff2" as="font" crossorigin>
<!-- Next page -->
<link rel="prefetch" href="/dashboard">
<!-- Third-party -->
<link rel="preconnect" href="https://api.example.com">
<link rel="dns-prefetch" href="https://cdn.example.com">Cas d'usage : Accélérer le chargement des fonts critiques, des pages suivantes probables et des APIs tierces.
Configuration qui définit comment Temporal retente une Activity en échec : intervalle initial, backoff, nombre max de tentatives et erreurs non-retentables.
Rappeler un ami qui ne répond pas : d'abord après 1 min, puis 5 min, puis 30 min, avec un maximum de 5 essais.
const retryPolicy = {
initialInterval: '1s',
backoffCoefficient: 2,
maximumAttempts: 5,
nonRetryableErrorTypes: ['InvalidInputError'],
};Cas d'usage : Configurer des retries intelligents sur les appels API externes pour absorber les erreurs transitoires.
Stockage objet accessible via l'API S3 d'Amazon, devenu un standard. Compatible avec MinIO, Cloudflare R2, DigitalOcean Spaces pour éviter le vendor lock-in.
Un entrepôt de stockage standardisé : les cartons (fichiers) se rangent de la même façon quel que soit l'entrepôt.
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
const s3 = new S3Client({ region: 'eu-west-1' });
await s3.send(new PutObjectCommand({
Bucket: 'my-uploads',
Key: `avatars/${userId}.webp`,
Body: fileBuffer,
}));Cas d'usage : Stocker les fichiers uploadés (images, documents, vidéos) hors du serveur applicatif.
Pattern de gestion de transactions distribuées où chaque étape a une action compensatoire. En cas d'échec, les compensations sont exécutées en ordre inverse.
Annuler une réservation de vacances : d'abord l'hôtel, puis le vol, puis la voiture, dans l'ordre inverse des réservations.
const compensations = [];
try {
await chargeCard(order); compensations.push(() => refund(order));
await reserveStock(order); compensations.push(() => releaseStock(order));
await shipOrder(order);
} catch (err) {
for (const comp of compensations.reverse()) await comp();
}Cas d'usage : Gérer des transactions multi-services (paiement + stock + livraison) sans verrou distribué.
Standard XML d'authentification fédérée principalement utilisé en entreprise. L'Identity Provider émet des assertions XML signées pour authentifier l'utilisateur auprès du Service Provider.
Un passeport diplomatique émis par un pays (IdP) et reconnu à la frontière d'un autre (SP).
// SAML config (passport-saml)
{
entryPoint: 'https://idp.corp.com/saml/sso',
issuer: 'my-app',
cert: idpCertificate,
callbackUrl: 'https://app.com/auth/saml/callback',
}Cas d'usage : Intégrer une app SaaS avec l'Active Directory ou le SSO d'une grande entreprise.
Pratiques et outils (Vault, AWS Secrets Manager, doppler) pour stocker, distribuer et rotationner les secrets applicatifs hors du code source.
Un coffre-fort numérique centralisé dont seuls les employés autorisés connaissent la combinaison, changée régulièrement.
// Using AWS Secrets Manager
const secret = await secretsManager.getSecretValue({
SecretId: 'prod/db/credentials'
}).promise();
const { username, password } = JSON.parse(secret.SecretString);Cas d'usage : Centraliser et sécuriser tous les secrets (DB, API, clés) avec rotation automatique en production.
Protocole HTTP unidirectionnel serveur vers client pour le streaming d'événements. Plus simple que WebSocket quand la communication bidirectionnelle n'est pas nécessaire.
Une radio FM : le serveur diffuse et les clients écoûtent, sans pouvoir répondre par le même canal.
// Server (Node.js)
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
setInterval(() => {
res.write(`data: ${JSON.stringify(getUpdate())}\n\n`);
}, 1000);Cas d'usage : Notifications serveur, flux d'actualités, suivi de progression d'un traitement long.
Sessions stockent l'état côté serveur (cookie + store), tokens sont stateless (JWT côté client). Sessions offrent révocation facile, tokens offrent scalabilité horizontale.
Session = badge gardé au registre de l'accueil. Token = badge avec toutes les infos imprimées dessus.
// Session: server stores state
req.session.userId = user.id; // Stored in Redis
// Token: client stores state
const token = jwt.sign({ userId: user.id }, secret);
res.json({ accessToken: token });Cas d'usage : Choisir sessions pour les apps monolithiques classiques, tokens pour les API/microservices.
Bibliothèque temps réel au-dessus de WebSocket avec fallback automatique. Les Rooms groupent les clients, les Namespaces séparent les canaux logiques.
Un immeuble (namespace) avec des appartements (rooms) : chaque message va à la bonne pièce du bon étage.
const chat = io.of('/chat');
chat.on('connection', (socket) => {
socket.join('room-42');
chat.to('room-42').emit('message', {
user: socket.id, text: 'Hello!'
});
});Cas d'usage : Construire un chat multi-salons avec reconnexion automatique et support des anciens navigateurs.
API navigateur qui déclare, en JSON dans une balise <script type="speculationrules"> ou un en-tête HTTP, quelles pages précharger (prefetch) ou pré-rendre entièrement en arrière-plan (prerender) : au clic, la navigation est instantanée. Le niveau d'agressivité (eagerness) va de « immédiate » à « conservative » (au survol ou au mousedown). Supportée par les navigateurs Chromium ; MDN la classe encore en disponibilité limitée.
Le serveur qui commence à préparer le dessert dès qu'il vous voit regarder la carte : si vous commandez, il arrive tout de suite ; sinon, une petite perte.
<!-- Pré-rendu des liens produit quand l'utilisateur les survole -->
<script type="speculationrules">
{
"prerender": [{
"where": { "and": [
{ "href_matches": "/produit/*" },
{ "not": { "selector_matches": ".no-prerender" } }
]},
"eagerness": "moderate"
}],
"prefetch": [{ "urls": ["/panier", "/compte"], "eagerness": "conservative" }]
}
</script>Cas d'usage : Sites de contenu ou e-commerce où la page suivante est prévisible ; gain direct sur le LCP des navigations internes.
Bibliothèque JavaScript pour modéliser la logique applicative comme des machines à états finis. Garantit que seules les transitions valides sont possibles.
Un distributeur automatique qui ne peut être que dans un état à la fois : en attente, en paiement, en distribution.
import { createMachine } from 'xstate';
const orderMachine = createMachine({
initial: 'pending',
states: {
pending: { on: { PAY: 'processing' } },
processing: { on: { SUCCESS: 'shipped', FAIL: 'pending' } },
shipped: { on: { DELIVER: 'delivered' } },
delivered: { type: 'final' },
},
});Cas d'usage : Modéliser des workflows complexes (commande, formulaire multi-étapes, lecteur vidéo) sans bugs d'état.
Extension des FSM avec états hiérarchiques (imbriqués), parallèles et historiques. Permet de modéliser des systèmes complexes tout en gardant la rigueur des FSM.
Un organigramme d'entreprise avec des départements (états parents) contenant des équipes (sous-états) travaillant en parallèle.
const machine = createMachine({
type: 'parallel',
states: {
player: { initial: 'paused',
states: { paused: {}, playing: {} } },
volume: { initial: 'normal',
states: { muted: {}, normal: {}, loud: {} } },
},
});Cas d'usage : Modéliser des interfaces complexes avec plusieurs sous-systèmes indépendants (lecteur média, formulaires).
Protocoles de streaming adaptatif qui découpent la vidéo en segments et ajustent la qualité selon la bande passante. HLS (Apple) et DASH (standard ouvert) dominent le marché.
Un robinet qui ajuste automatiquement le débit d'eau selon la pression disponible dans les tuyaux.
// Video.js HLS player
import Hls from 'hls.js';
const hls = new Hls();
hls.loadSource('https://cdn.example.com/video/master.m3u8');
hls.attachMedia(videoElement);
hls.on(Hls.Events.MANIFEST_PARSED, () => {
videoElement.play();
});Cas d'usage : Diffuser du contenu vidéo à grande échelle avec adaptation automatique à la qualité réseau.
Unité de travail exécutée par un Worker Temporal, représentant une action avec effets de bord (appel API, écriture DB). Les Activities peuvent être retentées indépendamment.
Les étapes individuelles d'une recette de cuisine : chacune peut être refaite sans recommencer tout le plat.
// Activity definition
async function sendEmail(to, subject, body) {
const result = await mailer.send({ to, subject, body });
return result.messageId;
}
// Registered in worker
const activities = { sendEmail, chargeCard };Cas d'usage : Encapsuler chaque appel externe (paiement, email, API tierce) pour bénéficier du retry automatique.
Mécanisme synchrone pour lire l'état interne d'un Workflow en cours sans le modifier. Retourne une valeur immédiatement.
Regarder par la vitre d'un four pour vérifier la cuisson sans ouvrir la porte.
const statusQuery = defineQuery('getStatus');
setHandler(statusQuery, () => ({
step: currentStep,
progress: completedSteps / totalSteps,
}));Cas d'usage : Exposer la progression d'un processus long dans une UI sans interférer avec l'exécution.
Planification native de Temporal pour lancer des Workflows à intervalles réguliers (cron-like). Gère les chevauchements, les pauses et les rattrappages.
Un réveil programmable qui sonne chaque jour à la même heure, même si vous dormez encore quand il sonne.
await client.schedule.create({
scheduleId: 'daily-report',
spec: { cronExpressions: ['0 8 * * *'] },
action: {
type: 'startWorkflow',
workflowType: 'generateReport',
},
});Cas d'usage : Remplacer les cron jobs fragiles par des schedules durables avec retry et monitoring intégrés.
Mécanisme pour envoyer des données à un Workflow en cours d'exécution depuis l'extérieur. Le Signal est asynchrone et modifie l'état interne du Workflow.
Glisser un post-it sous la porte d'un collègué occupé pour lui transmettre une info sans l'interrompre.
// Define signal
const approveSignal = defineSignal('approve');
// Handle in workflow
setHandler(approveSignal, (data) => {
approved = true;
approver = data.userId;
});Cas d'usage : Permettre une approbation humaine ou un événement externe d'influencer un Workflow en cours.
Pause durable dans un Workflow Temporal qui survit aux redémarrages du Worker. Peut durer de secondes à des mois sans consommer de ressources.
Un minuteur de cuisine qui continue de tourner même si vous quittez la maison et revenez.
import { sleep } from '@temporalio/workflow';
// Wait 7 days for payment
await sleep('7 days');
if (!paymentReceived) {
await cancelOrder(orderId);
}Cas d'usage : Implémenter des délais métier (période d'essai, rappels, expiration) de manière fiable.
Système de recherche et filtrage des Workflows Temporal via des attributs personnalisés. Permet de lister et monitorer les exécutions en cours ou terminées.
Le tableau de bord d'un centre logistique montrant l'état de tous les colis en temps réel.
// Search workflows
const results = await client.workflow.list({
query: `WorkflowType='OrderWorkflow'
AND ExecutionStatus='Running'
AND CustomField='vip'`,
});Cas d'usage : Construire des dashboards opérationnels pour suivre les processus métier en production.
Processus qui écoûte une Task Queue Temporal et exécute les Workflows et Activities assignés. Plusieurs Workers peuvent partager la même queue pour la scalabilité.
Un employé de bureau qui prend des dossiers dans une pile partagée et les traite un par un.
import { Worker } from '@temporalio/worker';
const worker = await Worker.create({
workflowsPath: require.resolve('./workflows'),
activities,
taskQueue: 'order-queue',
});
await worker.run();Cas d'usage : Déployer des Workers scalables horizontalement pour absorber les pics de charge sur les tâches asynchrones.
Fonction durable orchestrée par Temporal qui survit aux pannes et redémarrages. Le code s'exécute de manière déterministe et reprend automatiquement là où il s'est arrêté.
Un GPS qui recalcule automatiquement l'itinéraire après chaque détour, sans jamais oublier la destination finale.
// Temporal Workflow
async function orderWorkflow(order) {
await validatePayment(order);
await reserveStock(order);
await shipOrder(order);
await notifyCustomer(order);
return { status: 'completed' };
}Cas d'usage : Orchestrer des processus métier longs (commandes, onboarding) nécessitant fiabilité et traçabilité.
Émail déclenché par une action utilisateur (confirmation, facture, reset password) via un service dédié (SendGrid, Resend, SES). Distinct de l'email marketing.
Le reçu que la caissière vous imprime automatiquement après chaque achat.
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
await resend.emails.send({
from: '[email protected]',
to: user.email,
subject: 'Confirm your account',
react: <ConfirmEmail url={confirmUrl} />,
});Cas d'usage : Envoyer des emails de confirmation, reset password et factures avec un taux de délivrabilité élevé.
Bibliothèque qui expose des procédures TypeScript côté serveur et les rend appelables côté client avec des types inférés de bout en bout, sans schéma ni génération de code : une signature change, le client ne compile plus. tRPC v11, annoncée le 21 mars 2025, reste très compatible avec la v10 et ajoute le streaming de réponses (httpBatchStreamLink), les contenus non JSON (FormData, Blob, fichiers) et des fonctions serveur expérimentales. Pertinent quand front et back partagent un même monorepo TypeScript.
Deux collègués qui parlent la même langue dans le même bureau n'ont pas besoin d'un traducteur assermenté (OpenAPI) : ils se comprennent à la virgule près.
// server/router.ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
const t = initTRPC.create();
export const appRouter = t.router({
userById: t.procedure
.input(z.object({ id: z.string() }))
.query(({ input }) => db.user.findUnique({ where: { id: input.id } })),
});
export type AppRouter = typeof appRouter;
// client.ts – aucun type dupliqué
const trpc = createTRPCClient<AppRouter>({ links: [httpBatchLink({ url: '/api/trpc' })] });
const user = await trpc.userById.query({ id: 'u_1' }); // user typéCas d'usage : Application full-stack TypeScript (Next.js, monorepo) où l'API n'est consommée que par vos propres fronts.
API navigateur, pilotée par CSP (require-trusted-types-for 'script'), qui interdit de passer une chaîne brute aux puits d'injection du DOM (innerHTML, eval, script.src…) : seuls des objets TrustedHTML/TrustedScript créés par une politique déclarée sont acceptés, sinon TypeError. C'est la défense la plus efficace contre le XSS basé sur le DOM. Disponible dans Chrome et Edge depuis la version 83 (2020), Safari 26 (septembre 2025) et Firefox 148 (février 2026) : statut Baseline depuis février 2026.
Un vigile qui n'accepte à l'entrée que des invitations tamponnées par le bureau d'accueil : plus personne ne rentre avec un papier écrit à la main.
// En-tête CSP côté serveur :
// Content-Security-Policy: require-trusted-types-for 'script'; trusted-types app
// Une seule politique, un seul endroit où l'on assainit
const policy = trustedTypes.createPolicy('app', {
createHTML: (input) => DOMPurify.sanitize(input),
createScriptURL: (url) => {
if (new URL(url, location.href).origin !== location.origin) throw new Error('URL refusée');
return url;
},
});
el.innerHTML = policy.createHTML(userInput); // OK : TrustedHTML
el.innerHTML = userInput; // TypeError : bloqué par CSPCas d'usage : Applications à forte surface DOM (éditeurs, dashboards, CMS) où un XSS DOM aurait un impact fort ; à déployer d'abord en mode Report-Only.
Temps entre la requête HTTP et la réception du premier octet de réponse. Mesure la latence serveur incluant DNS, connexion TLS et traitement backend.
Le temps entre la commande au restaurant et le moment où le serveur commence à apporter le plat.
// Measure TTFB
const { responseStart, requestStart } = performance.getEntriesByType('navigation')[0];
const ttfb = responseStart - requestStart;
console.log(`TTFB: ${ttfb}ms`); // Target: < 800msCas d'usage : Diagnostiquer les problèmes de latence serveur (DB lente, absence de cache, serveur éloigné).
Outil de build incrémental pour monorepos créé par Vercel : il met en cache les sorties des tâches et n'exécute que ce qui a changé. Turborepo 2.0, publié le 4 juin 2024, renommé la clé « pipeline » de turbo.json en « tasks », passe sous licence MIT, ajoute un mode watch et une interface terminal interactive ; la migration se fait avec npx @turbo/codemod migrate.
Un chef cuisinier qui ne recuit que les plats dont les ingrédients ont changé, servant les autres depuis le frigo.
// turbo.json (Turborepo 2.x)
{
"$schema": "https://turborepo.dev/schema.json",
"tasks": {
"build": { "dependsOn": ["^build"], "outputs": ["dist/**"] },
"test": { "dependsOn": ["build"] },
"lint": {},
"dev": { "cache": false, "persistent": true }
}
}Cas d'usage : Accélérer les builds CI/CD d'un monorepo en ne rebuild que les packages modifiés.
Bibliothèque de validation TypeScript modulaire et entièrement « tree-shakable » : chaque validateur est une fonction importée séparément, si bien qu'un schéma simple pèse environ 1 ko dans le bundle. Né en juillet 2023 d'un mémoire de fin d'études visant à réduire la taille des bibliothèques de plus de 90 %, Valibot a atteint la version 1.0 le 19 mars 2025. Alternative à Zod quand le poids côté client compte (edge, mobile, formulaires).
Au lieu d'emporter toute la boîte à outils, on ne glisse dans la poche que le tournevis et la clé dont on a besoin.
import * as v from 'valibot';
// Composition par fonctions : seul ce qui est importé est embarqué
const Login = v.object({
email: v.pipe(v.string(), v.email(), v.maxLength(120)),
password: v.pipe(v.string(), v.minLength(12, '12 caractères minimum')),
});
type Login = v.InferOutput<typeof Login>;
const result = v.safeParse(Login, await req.json());
if (!result.success) {
return res.status(400).json(v.flatten(result.issues));
}
await auth(result.output);Cas d'usage : Validation côté client ou en edge runtime où chaque kilo-octet compte ; compatible avec la spécification Standard Schema utilisée par tRPC, TanStack et autres.
Stripe notifie votre serveur des événements (paiement réussi, abonnement annulé) par requêtes HTTP signées. Trois règles : vérifier la signature (en-tête Stripe-Signature) sur le corps brut, répondre 2xx vite puis traiter en tâche de fond, et rendre le traitement idempotent car un même événement peut arriver plusieurs fois (Stripe réessaie avec délai croissant pendant trois jours en mode live, l'identifiant evt_ restant identique). On stocke les identifiants d'événements traités.
Le facteur peut sonner deux fois avec le même recommandé : on vérifie le cachet, on signe l'accusé tout de suite, et on note le numéro pour ne pas ouvrir deux fois le même colis.
// Express : corps BRUT obligatoire pour vérifier la signature
app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), async (req, res) => {
let event;
try {
event = stripe.webhooks.constructEvent(req.body, req.headers['stripe-signature'], WEBHOOK_SECRET);
} catch { return res.status(400).send('Signature invalide'); }
// Idempotence : INSERT échoue si evt_ déjà vu (clé primaire)
const fresh = await db.insertIgnore('stripe_events', { id: event.id, type: event.type });
if (!fresh) return res.sendStatus(200); // doublon → on ignore
await queue.add('stripe', event); // traitement asynchrone
res.sendStatus(200); // répondre vite
});Cas d'usage : Activer un abonnement, débloquer un téléchargement ou envoyer une facture uniquement quand Stripe confirme le paiement, sans jamais le faire deux fois.
API navigateur pour la communication peer-to-peer en temps réel (audio, vidéo, données) sans passer par un serveur central. Utilise STUN/TURN pour la traversée NAT.
Un talkie-walkie numérique qui connecte deux personnes directement sans passer par un standard téléphonique.
const pc = new RTCPeerConnection({ iceServers });
const stream = await navigator.mediaDevices.getUserMedia({
video: true, audio: true
});
stream.getTracks().forEach(t => pc.addTrack(t, stream));
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);Cas d'usage : Visioconférence, partage d'écran, transfert de fichiers P2P dans le navigateur.
Protocole de communication bidirectionnelle persistante entre client et serveur sur une seule connexion TCP. Idéal pour les données temps réel.
Un appel téléphonique ouvert en continu plutôt que d'envoyer des SMS un par un.
const ws = new WebSocket('wss://api.example.com');
ws.onopen = () => ws.send(JSON.stringify({ type: 'subscribe', channel: 'prices' }));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
updateUI(data);
};Cas d'usage : Chat en temps réel, cours de bourse, notifications live, jeux multijoueurs.
Technique Temporal pour déployer de nouvelles versions de code Workflow sans casser les exécutions en cours. Utilise patching ou Task Queue versioning.
Changer le moteur d'un avion en vol : les anciens passagers gardent l'ancien moteur, les nouveaux ont le nouveau.
import { patched } from '@temporalio/workflow';
if (patched('new-validation')) {
await newValidation(order);
} else {
await oldValidation(order);
}Cas d'usage : Déployer des changements de logique métier en production sans interrompre les processus en cours.
Bibliothèque TypeScript de validation de schémas avec inférence de types. Zod 4, désormais stable, annonce un parsing de chaînés 14 fois plus rapide et de tableaux 7 fois plus rapide que Zod 3, une empreinte de bundle divisée par plus de deux, une conversion JSON Schema de première classe (z.toJSONSchema), un paramètre d'erreur unifié « error », des registres de métadonnées et une variante Zod Mini (API fonctionnelle, très compacte). Zod 4 a d'abord été publié sous le sous-chemin « zod/v4 » pour laisser l'écosystème migrer.
Le même contrôleur aux frontières, mais qui lit les passeports dix fois plus vite et tient dans une valise deux fois plus petite.
import * as z from 'zod'; // Zod 4
const Order = z.object({
email: z.email(), // validateurs au niveau racine
qty: z.int().positive({ error: 'Quantité invalide' }), // erreur unifiée
tags: z.array(z.string()).max(5).default([]),
});
type Order = z.infer<typeof Order>;
const r = Order.safeParse(await req.json());
if (!r.success) return res.status(400).json(z.treeifyError(r.error));
// OpenAPI / outils : schéma JSON généré nativement
export const orderJsonSchema = z.toJSONSchema(Order);Cas d'usage : Valider les entrées d'API, les variables d'environnement, les formulaires, et générer l'OpenAPI depuis la même source.