Introduction
La planification de capacité pour React Native consiste à prédire le débit client, backend et facturation dont votre application a besoin sans saturer les ressources des appareils ni les coûts serveur. Le gain : moins de crashs et d'ANR, une expérience fluide en pointe, et une montée en charge prévisible pour vos API et flux de paiement.
Ce guide vous donne un workflow clair, des formules de dimensionnement et des exemples pratiques couvrant Expo, Android, les API REST, Google Play Billing et Stripe. Il se termine par un pilote local sûr à exécuter pour dérisquer la croissance.
Vue d'ensemble du workflow
Utilisez un flux simple, reproductible à chaque fonctionnalité majeure et chaque release :
- Définir les charges de travail et les objectifs
- Public cible et gammes d'appareils : Android entrée, milieu, haut de gamme ; iOS récent si pertinent.
- Forme de la charge : DAU/WAU, sessions par utilisateur, écrans par session, requêtes par écran, tailles upload/download, taux d'achat.
- Objectifs : démarrage à froid p75/p95, temps avant interactivité (TTI), fluidité du défilement, latence API p95, temps de finalisation d'achat.
- Établir la référence (baseline) de l'app
- Activer le moteur JS de production (par exemple Hermes) dans un build release.
- Mesurer : démarrage à froid, TTI, temps de frame JS et UI, mémoire RSS et tas JS, réseau par écran.
- Enregistrer les chiffres sur au moins 3 appareils (entrée, milieu, haut de gamme).
- Modéliser la pointe et la concurrence
- Calculer les utilisateurs actifs en pointe et la concurrence de requêtes par écran.
- Convertir les actions utilisateur en RPS API, bande passante images, et événements d'achat/facturation.
- Fixer les budgets
- Client : travail JS par frame, travail UI par frame, mémoire par écran, réseau par écran.
- Serveur : RPS par endpoint, budgets de latence p95, débit API d'achat, capacité des workers webhook.
- Implémenter les contrôles
- Pagination, regroupement de requêtes, limites de concurrence, mise en cache, debouncing.
- Backoff, timeouts et annulation pour les appels réseau.
- Idempotence et files bornées pour les flux paiement et webhook.
- Tester sous contrainte
- Simuler réseaux lents, pertes de paquets, listes volumineuses, actions en rafale.
- Lancer des tests de charge API avec des mélanges de trafic réalistes.
- Surveiller et itérer
- Suivre les signaux listés ci-dessous. Ajuster budgets et contrôles avant chaque événement de croissance (campagnes, lancements, fêtes).
Ce plan clair réduit le retravail car chaque étape isole les décisions et les rend mesurables.
Modèle de dimensionnement et entrées
Traduisez les comportements en chiffres sur lesquels raisonner. Commencez large, puis affinez.
Budgets de temps côté client
- Cible 60 fps = 16,7 ms par frame.
- Budget travail thread JS sous 4–6 ms typique, pics sous 10 ms. Un coupable fréquent : parser un payload JSON de 200 Ko de façon synchrone sur le thread JS — le découper avec
setImmediateou paginer côté serveur. - Budget travail thread UI sous 8–10 ms typique.
- Différer le travail non urgent vers l'idle avec
InteractionManagerou l'étaler sur plusieurs frames.
Budgets mémoire (focus Android)
- Maintenir le RSS en régime permanent bien en dessous des limites de l'appareil. Viser sous 200–300 Mo sur appareils milieu de gamme, bien moins sur entrée de gamme.
- Éviter les bitmaps décodés volumineux en mémoire. Redimensionner côté serveur ou au minimum choisir des tailles correspondant aux dimensions à l'écran.
- Utiliser la virtualisation
FlatList/SectionListetremoveClippedSubviewspour limiter le nombre de vues vivantes. - Fuite typique : oublier d'annuler les requêtes d'images dans
onEndReached— les lignes se démontent mais les fetches continuent de résoudre et de mettre à jour l'état.
Budgets réseau
- Exemple écran liste : 20 items, chacun avec image 100 Ko après mise en cache et redimensionnement.
- Budget par page : environ 2 Mo plus JSON (disons 50–150 Ko).
- Limiter les fetches concurrents à 4 pour limiter la contention radio et la consommation batterie sur réseaux mobiles ; une concurrence plus élevée encombre le thread JS avec les gestionnaires de réponses.
- Précharger la page suivante quand l'utilisateur défile au-delà de 70 %.
Débit API
- Formule RPS de pointe :
QPS_peak = utilisateurs_concurrents_peak * req_par_user_par_minute / 60. - Exemple : 5 000 utilisateurs concurrents générant 12 requêtes/minute donnent 1 000 QPS. Avec 50 % de marge, prévoir 1 500 QPS de capacité.
Débit achats et facturation
- Supposer qu chaque achat crée 2–3 événements webhook bout-en-bout :
purchase.created,purchase.confirmed,receipt.validated. Si vous attendez 30 achats/minute en pointe, dimensionner les workers webhook pour au moins 90 événements/minute, avec 2x de marge pour les rafales. - Maintenir un budget de latence d'achat bout-en-bout (par exemple p95 sous 5 secondes du tap à l'écran de confirmation), et aligner les timeouts client et serveur.
Stockage et files hors-ligne
- Borné la taille des files d'événements hors-ligne (par exemple 100–500 items) avec backpressure et politiques de suppression pour les événements non critiques.
Signaux, limites et marges de sécurité
Signaux client clés
- Frames longues et drops JS/UI pendant défilement et gestes.
- Temps de démarrage et TTI.
- Croissance RSS mémoire et tas JS ; pression GC.
- Taux ANR (Android) et utilisateurs sans crash.
Signaux réseau et serveur clés
- Latence API p95/p99 et taux d'erreur par endpoint.
- Retentatives, timeouts, événements d'ouverture circuit breaker.
- Profondeur file webhook, latence traitement, compte dead-letter.
Limites à respecter
- Rendu : budget frame 16,7 ms ; éviter layouts coûteux et bridges synchrones.
- Mémoire : être conservateur sur Android entrée de gamme où les killers d'arrière-plan sont agressifs.
- Bridge : éviter d'envoyer de gros blobs JSON par frame ; regrouper et compresser si possible.
Marges de sécurité
- Conserver 30–50 % de marge pour CPU, mémoire et débit serveur autour des pointes attendues.
- Utiliser des rate limiters et backpressure côté client et serveur.
- Concevoir une dégradation gracieuse : UI squelette, tailles de page réduites, travail non critique différé.
Exemples pratiques
1) Expo + API REST : écran liste avec images
Objectif : défilement 60 fps fluide sur une liste produits tout en récupérant images et JSON.
Budgets client
- JS par frame sous 6 ms.
- UI par frame sous 10 ms.
- Réseau par page environ 2 Mo.
Réglages FlatList
<FlatList
data={items}
keyExtractor={(it) => it.id}
renderItem={renderItem}
initialNumToRender={10}
maxToRenderPerBatch={10}
windowSize={5}
removeClippedSubviews
onEndReachedThreshold={0.7}
onEndReached={loadNextPage}
/>
Préchargement d'images avec file contrainte
const queue: Array<() => void> = [];
let active = 0;
const LIMIT = 4;
function runNext() {
if (active >= LIMIT) return;
const task = queue.shift();
if (!task) return;
active++;
task();
}
function limitedFetch(url: string): Promise<Response> {
return new Promise((resolve, reject) => {
const task = () => {
fetch(url)
.then(resolve)
.catch(reject)
.finally(() => { active--; runNext(); });
};
queue.push(task);
runNext();
});
}
async function prefetchImage(uri: string) {
await limitedFetch(uri);
}
Mesure locale
console.time('list-first-render');
// après first meaningful paint
console.timeEnd('list-first-render');
Si le défilement saccade, réduire les fetches d'images concurrents à 2, réduire les images, ou différer les items non visibles.
2) Budgétisation performance Android pour éviter ANR et OOM
- Maintenir un faible nombre de vues vivantes avec la virtualisation. Éviter les
FlatListimbriquées ; utiliserSectionList. - Éviter le parsing JSON synchrone volumineux sur le thread JS. Si les payloads sont gros, paginer côté serveur ou découper le travail sur plusieurs ticks avec
setImmediateetInteractionManager. - Sous-échantillonner les images à la taille d'affichage. Libérer les ressources images quand les lignes sortent de l'écran.
- Surveiller la mémoire sur appareils entrée de gamme ; tester avec sessions longues (20–30 minutes) pour révéler les fuites.
3) Gestion des pics Google Play Billing et Stripe
Scénario : une promo de 20 minutes génère un pic d'achats 10x.
Client
- Utiliser des clés d'idempotence pour les appels de confirmation d'achat.
- Imposer des timeouts réseau (par exemple 5–10 s) et retries avec backoff exponentiel.
- Afficher des reçus tolérants au hors-ligne et réessayer en arrière-plan si besoin.
Serveur
- Cible débit : si la base est 30 achats/min, prévoir 300/min pendant la promo. Avec 2x marge, dimensionner pour 600/min.
- Webhooks : supposer 2–3 événements par achat. Prévoir workers pour 1 200–1 800 événements/minute.
- Garder les handlers webhook idempotents et rapides ; différer le travail lourd vers une file interne.
Esquisse worker webhook avec concurrence bornée
type Job = { id: string; payload: any };
const inflight = new Set<string>();
const CONCURRENCY = 16; // ajuster selon CPU et I/O
async function handle(job: Job) {
if (inflight.has(job.id)) return; // garde idempotence
inflight.add(job.id);
try {
// valider signature, mettre à jour état commande, enfile follow-ups
} finally {
inflight.delete(job.id);
}
}
Surveiller profondeur file et latence traitement ; autoscaler les workers avant la fenêtre promo.
Plan Pilote Local
Objectif : prouver qu'un écran critique et un parcours d'achat respectent les budgets sur appareils Android entrée, milieu, haut de gamme, et que votre API et workers webhook gèrent un mini-pic réaliste.
Périmètre (étroit, mesurable)
- Écran : liste produits avec images et pagination.
- Flux : un achat consommable bout-en-bout.
Étapes
- Définir les cibles : défilement liste < 5 % frames longues, TTI < 2,5 s sur milieu de gamme, API p95 < 300 ms, achat p95 < 5 s.
- Implémenter réglages
FlatListet file de fetch avecLIMIT=4. - Redimensionner images aux tailles d'affichage et activer mise en cache HTTP.
- Ajouter timeouts et backoff aux appels réseau ; imposer clés d'idempotence dans les appels d'achat.
- Créer un petit worker webhook avec concurrence bornée et logs.
- Simuler réseaux lents (3G/4G lent) et 2 % perte paquets ; vérifier cibles défilement et achat.
- Lancer une charge locale contre l'API d'achat à 2x la charge pilote attendue ; confirmer budgets latence et erreurs.
- Documenter budgets et résultats. Si cibles manquées, ajuster concurrence, tailles de batch, tailles images, puis relancer.
Ce pilote est étroit, mesurable, et facile à inspecter localement avant tout déploiement plus large.
Conclusion
La planification de capacité en React Native commence sur l'appareil : protéger temps de frame, mémoire et batterie avec budgets et contrôles clairs. Lier les actions client au débit serveur, et dimensionner vos endpoints REST et webhooks facturation avec marge réaliste.
Adoptez le workflow, lancez le pilote local, et verrouillez vos budgets et signaux. Revalidez les hypothèses avant lancements et promotions, et montez en charge avant la croissance planifiée. Avec exemples pratiques et petit pilote vérifié, vous pouvez livrer en confiance et éviter les surprises coûteuses.