0Pricing
DSA Interview Prep · Leçon

Cadre d’entretien de conception de systèmes

Parcourez le cadre RADIO en cinq étapes (Requirements, API, Data, Infrastructure, Optimise) et entraînez-vous à l’appliquer à un raccourcisseur d’URL.

Cadre d’entretien de conception de systèmes est une leçon DSA Interview Prep gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DSA Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DSA Interview Prep comprend 4 leçons au total.

Pourquoi la conception de systèmes est importante en entretien

Les entretiens de conception de systèmes évaluent votre capacité à raisonner à grande échelle — comment concevriez-vous Twitter, YouTube ou un raccourcisseur d'URL pour des milliards d'utilisateurs ? Contrairement aux problèmes de programmation qui ont une seule réponse correcte, la conception de systèmes est ouverte : vous devez faire des compromis et les justifier. Les postes de niveau confirmé et de responsable technique consacrent exclusivement 30 à 45 minutes à cette partie.

Les intervieweurs évaluent votre capacité à clarifier les exigences, à estimer la charge, à proposer une architecture de haut niveau, à approfondir les composants clés et à discuter des compromis, tout en communiquant clairement. Un cadre structuré vous empêche de digresser et vous garantit de couvrir toutes les dimensions essentielles.

# System design is not about a single correct answer.
# Interviewers look for:
eval_criteria = [
    'Ability to clarify requirements before designing',
    'Back-of-envelope capacity estimation',
    'High-level architecture with clear components',
    'Data modelling and storage choice',
    'Handling scalability (10x, 100x load)',
    'Trade-off discussion (consistency vs availability, etc.)',
    'Communication: talking through decisions as you make them',
]
for c in eval_criteria:
    print('-', c)

Présentation du cadre RADIO

Le cadre RADIO fournit une structure reproductible en cinq étapes pour tout entretien de conception de systèmes :

  • R — Exigences : fonctionnelles et non fonctionnelles
  • A — Conception de l'API : quelles opérations le système expose-t-il ?
  • D — Modèle de données : quelles données sont stockées et de quelle manière ?
  • I — Infrastructure : composants de haut niveau (serveurs, files d'attente, caches)
  • O — Optimiser : goulots d'étranglement, mise en cache, partitionnement, réplication

Parcourez toujours ces étapes dans l'ordre, mais revenez aux étapes précédentes et affinez-les lorsque de nouvelles informations apparaissent. Consacrez approximativement le même temps à chaque phase. Ne commencez jamais directement par dessiner des blocs sans avoir d'abord clarifié les exigences.

RADIO = {
    'R': 'Requirements — What must the system do? What scale?',
    'A': 'API         — Define endpoints/operations the system exposes',
    'D': 'Data Model  — Entities, schemas, storage types',
    'I': 'Infra       — High-level architecture: servers, queues, caches, CDN',
    'O': 'Optimise    — Identify and address bottlenecks, trade-offs',
}
for step, desc in RADIO.items():
    print(f'[{step}] {desc}')

print('\nTiming guide for a 45-min interview:')
print('  R: 5 min | A: 5 min | D: 10 min | I: 15 min | O: 10 min')

Étape R : clarifier les exigences

Ne commencez jamais la conception sans avoir clarifié les exigences. Interrogez votre interlocuteur sur les exigences fonctionnelles (ce que fait le système) et les exigences non fonctionnelles (échelle, latence, disponibilité). Pour un raccourcisseur d'URL :

  • Fonctionnelles : raccourcir une URL, rediriger vers l'URL d'origine, prendre éventuellement en charge des alias personnalisés et une expiration
  • Non fonctionnelles : combien d'URL par jour ? Le système est-il principalement sollicité en lecture ou en écriture ? Quelle exigence de disponibilité (99,9 % contre 99,99 %) ? Quelle latence est acceptable ?

Énoncer explicitement vos hypothèses montre votre maturité. Les intervieweurs donnent souvent des spécifications volontairement vagues pour vérifier que vous posez les bonnes questions. Deux minutes de clarification vous évitent de concevoir le mauvais système.

# Requirements questions for URL Shortener:
functional = [
    'Shorten a given URL to a 7-character alias',
    'Redirect short URL to original URL',
    'Allow custom aliases (optional)',
    'URL expiry (optional)',
    'Analytics: click count per URL (optional)',
]
non_functional = [
    '100 million new URLs per day (write: ~1160/sec)',
    '10:1 read:write ratio => 11,600 redirects/sec',
    'Redirects must be < 100ms p99 latency',
    '99.99% availability (< 1 hr downtime/year)',
    'URLs must be globally accessible',
]
print('Functional:')
for f in functional: print(' -', f)
print('\nNon-functional:')
for nf in non_functional: print(' -', nf)

Étape R : estimation à la louche

Après avoir défini les exigences, estimez la capacité. Cela montre que vous savez raisonner à l'échelle avant de proposer des solutions. Les principaux chiffres à déterminer sont les requêtes par seconde (RPS), le stockage nécessaire par jour et par an, la bande passante et la mémoire nécessaire à la mise en cache.

Utilisez des nombres ronds et faites librement des approximations. Les intervieweurs s'intéressent à l'ordre de grandeur, pas aux chiffres exacts. Exemple pour un raccourcisseur d'URL : 100M écritures/jour ÷ 86400 ≈ 1160 écritures/s. 10B lectures/jour ÷ 86400 ≈ 115K lectures/s. Chaque enregistrement d'URL fait environ 500 octets : 100M × 500B = 50 GB/jour, 18 TB/an.

# Back-of-envelope for URL Shortener
writes_per_day = 100_000_000        # 100 million URLs/day
read_write_ratio = 100              # 100:1 read/write
reads_per_day = writes_per_day * read_write_ratio
bytes_per_url = 500                 # url string + metadata
years_to_store = 5

print('=== Capacity Estimation ===')
print(f'Writes/sec:  {writes_per_day / 86400:.0f}')
print(f'Reads/sec:   {reads_per_day / 86400:,.0f}')
print(f'Storage/day: {writes_per_day * bytes_per_url / 1e9:.1f} GB')
print(f'Storage total ({years_to_store}y): {writes_per_day * bytes_per_url * 365 * years_to_store / 1e12:.1f} TB')

cache_hit_rate = 0.80
hot_urls = reads_per_day * (1 - cache_hit_rate)
print(f'\n80% cache hit rate: {cache_hit_rate*100}% of reads from cache')
print(f'DB reads/sec: {hot_urls / 86400:,.0f}')

Étape A : conception de l'API

Définissez l'ensemble des points d'accès de l'API — les opérations que le système expose aux clients et aux services internes. Précisez clairement la méthode HTTP, le chemin du point de terminaison, les paramètres de requête et le format de réponse. Cela sert de base au reste de la conception : tout le reste existe pour implémenter ces API.

Pour un raccourcisseur d'URL, les deux API principales sont : (1) POST /shorten pour créer une URL courte, (2) GET /{alias} pour rediriger. En option : DELETE /{alias} pour supprimer, GET /{alias}/stats pour les statistiques. Précisez les codes de réponse (201 Créé, 301 Redirection, 404 Introuvable).

# API Design for URL Shortener
apis = [
    {
        'method': 'POST',
        'path': '/api/v1/shorten',
        'request': '{"long_url": "https://...", "alias": "optional", "expires_at": "optional"}',
        'response': '201 Created: {"short_url": "https://short.ly/abc1234", "alias": "abc1234"}',
    },
    {
        'method': 'GET',
        'path': '/{alias}',
        'request': 'No body',
        'response': '301 Redirect to long_url (or 404 Not Found)',
    },
    {
        'method': 'GET',
        'path': '/api/v1/{alias}/stats',
        'request': 'Optional: date range query params',
        'response': '200 OK: {"clicks": 42000, "unique_visitors": 15000}',
    },
]
for api in apis:
    print(f'{api["method"]} {api["path"]}')
    print(f'  Request:  {api["request"]}')
    print(f'  Response: {api["response"]}')
    print()

Étape D : modèle de données

Le modèle de données définit ce que vous stockez et de quelle manière. Identifiez les entités principales et leurs attributs. Pour un raccourcisseur d'URL : une table urls avec alias (clé primaire), long_url, created_at, expires_at et user_id. Une table clicks facultative peut servir aux statistiques.

Choisir le bon type de stockage est essentiel : une base de données relationnelle pour les données structurées avec des requêtes complexes ; un stockage clé-valeur (Redis, DynamoDB) pour les recherches d'alias en O(1) à grande échelle ; un stockage d'objets (S3) pour les objets volumineux. Pour un raccourcisseur d'URL, un stockage clé-valeur indexé par alias est idéal pour les lectures, avec une base de données relationnelle pour les écritures et la gestion.

# Data model for URL Shortener

# Core table (PostgreSQL)
urls_schema = '''
CREATE TABLE urls (
    alias       VARCHAR(16) PRIMARY KEY,   -- e.g., 'abc1234'
    long_url    TEXT NOT NULL,
    user_id     UUID REFERENCES users(id),
    created_at  TIMESTAMP DEFAULT NOW(),
    expires_at  TIMESTAMP,
    click_count BIGINT DEFAULT 0
);
CREATE INDEX ON urls(user_id);
'''

# Cache layer (Redis) for hot reads
redis_schema = '''
alias  =>  long_url       # O(1) GET on cache hit
TTL = 24 hours (or until expiry)
Cache eviction: LRU
'''

print('PostgreSQL schema:')
print(urls_schema)
print('Redis cache:')
print(redis_schema)
print('Storage split: Redis for hot reads (~80%), PostgreSQL for writes and cold reads')

Étape I : infrastructure de haut niveau

Esquissez l'infrastructure de haut niveau : quels serveurs prennent en charge quelles responsabilités, comment les données circulent entre les composants et quels services externes sont utilisés. Pour un raccourcisseur d'URL à grande échelle :

  • Répartiteur de charge : distribue le trafic aux réplicas des services d'écriture et de lecture
  • Service d'écriture : génère l'alias, vérifie son unicité, écrit dans la base de données et invalide le cache
  • Service de lecture/redirection : consulte d'abord le cache Redis et se rabat sur la base de données en cas d'absence
  • Base de données relationnelle : source de vérité (avec des réplicas de lecture)
  • Grappe Redis : met en cache les correspondances d'URL fréquemment consultées pour des lectures en moins d'une milliseconde
# ASCII architecture sketch
architecture = '''
         Clients
            |
       [Load Balancer]
       /             \\
  [Write API]    [Read/Redirect API]
      |                  |  |
  [Alias Gen]       [Redis Cache]
      |                  |
  [PostgreSQL]---->[Read Replicas]

Alias Generation:
- Base62 encoding of auto-incrementing ID
- 62^7 = 3.5 trillion unique URLs (enough for 5 years at 100M/day)
- OR random 7-char Base62 with collision check
'''
print(architecture)
print('Key design decisions:')
print('  - Read/Write split: separate services for scalability')
print('  - Cache-aside pattern: read from Redis, fallback to DB')
print('  - 301 vs 302 redirect: 301 cached by browser (less load), 302 always hits server (analytics)')

Étape O : optimiser et gérer les goulots d'étranglement

La phase d'optimisation traite les goulots d'étranglement et permet de faire évoluer le système. Pour un raccourcisseur d'URL, les principales difficultés sont les suivantes : la latence des redirections (rapprochez Redis des utilisateurs à l'aide d'un CDN ou de caches en périphérie), l'unicité des alias à grande échelle (utilisez un serveur central de tickets ou un hachage avec détection des collisions) et le goulot d'étranglement des écritures en base de données (effectuez des écritures par lots ou asynchrones avec une file d'attente).

Discutez explicitement des compromis : les redirections 301 réduisent la charge du serveur, mais diminuent la précision des analyses ; les redirections 302 peuvent être suivies, mais ajoutent de la latence. Une expiration longue du cache réduit la charge de la base de données, mais risque de conserver des URL obsolètes. Montrer que vous comprenez ces tensions témoigne d'un raisonnement de niveau confirmé.

# Key optimisation discussion points
optimisations = {
    'Read latency': [
        'Redis cluster in multiple regions (CDN-edge caching)',
        '301 redirect for non-tracked URLs (client caches)',
        '302 redirect when click analytics are needed',
    ],
    'Write throughput': [
        'Async writes: accept request, enqueue to Kafka, batch-commit to DB',
        'Ticket server (centralised ID generator) to avoid UUID collision',
        'Or: hash(user_id + timestamp + random) with retry on collision',
    ],
    'Availability': [
        'Multi-AZ PostgreSQL with automatic failover',
        'Redis Sentinel or Redis Cluster for HA cache',
        'Health checks + circuit breaker on each service',
    ],
    'Storage': [
        'Partition urls table by hash(alias) for horizontal scaling',
        'Archive expired URLs to cold storage (S3)',
    ],
}
for area, points in optimisations.items():
    print(f'{area}:')
    for p in points: print(f'  - {p}')
    print()

Génération d'alias : encodage Base62

Un détail technique essentiel des raccourcisseurs d'URL est la génération d'alias courts et uniques. L'approche standard consiste à utiliser un identifiant entier ID auto-incrémenté provenant de la base de données et à l'encoder en Base62 (chiffres de 0 à 9, lettres de a à z et de A à Z). Une chaîne Base62 de 7 caractères peut représenter 62^7 ≈ 3 500 milliards d'URL uniques — suffisamment pour plusieurs décennies à raison de 100M par jour.

Cette méthode est sans collision (chaque ID est unique) et produit des chaînes courtes compatibles avec les URL. La correspondance ID→alias est déterministe et réversible. Le compromis : des ID séquentiels créent des alias prévisibles, ce qui pose un problème de sécurité. Mélangez l'alphabet Base62 ou utilisez un décalage du compteur pour réduire la prévisibilité.

import string

BASE62_CHARS = string.digits + string.ascii_lowercase + string.ascii_uppercase
BASE = 62

def encode_base62(num):
    if num == 0:
        return BASE62_CHARS[0]
    result = ''
    while num:
        result = BASE62_CHARS[num % BASE] + result
        num //= BASE
    return result

def decode_base62(s):
    result = 0
    for c in s:
        result = result * BASE + BASE62_CHARS.index(c)
    return result

# Generate aliases for IDs 1, 100, 1000, 10^9
for id_ in [1, 100, 1000, 1_000_000, 10**9, 3_521_614_606207]:
    alias = encode_base62(id_)
    decoded = decode_base62(alias)
    print(f'ID {id_:20,} => alias "{alias}" (len={len(alias)}) => decoded={decoded}')

Appliquer RADIO à la conception d'un fil Twitter

Appliquons brièvement RADIO à la conception d'un fil d'actualités de type Twitter pour montrer que le cadre se généralise :

  • R : les utilisateurs publient des messages, suivent d'autres utilisateurs et voient un fil de messages publiés par les personnes qu'ils suivent. Échelle : 300M utilisateurs, 500M messages/jour, le fil doit se charger en <2 s.
  • A : POST /tweets, GET /feed, GET /timeline/{user_id}
  • D : table tweets (id, user_id, content, created_at) ; table follows (follower_id, followee_id) ; cache du fil pour chaque utilisateur
  • I : le service de diffusion inscrit les nouveaux messages dans les fils des abonnés (pré-calculés) ; Cassandra pour les tables de suivi et de messages à forte charge d'écriture ; Redis pour les caches des fils
# Fan-out on Write vs Fan-out on Read trade-off
fan_out_strategies = {
    'Fan-out on Write (Push)': {
        'How': 'When user A posts, immediately write to all followers feeds',
        'Pro': 'O(1) feed read — feed is precomputed',
        'Con': 'Celebrities with 10M followers => 10M writes per post; very slow write',
        'Best for': 'Users with few followers (regular users)',
    },
    'Fan-out on Read (Pull)': {
        'How': 'When user reads feed, query followees tweets and merge',
        'Pro': 'Writes are fast (one DB write per tweet)',
        'Con': 'Feed read is slow: must query all N followees',
        'Best for': 'Celebrity accounts (few reads per post)',
    },
    'Hybrid': {
        'How': 'Push for regular users, pull for celebrities',
        'Pro': 'Balances read and write cost',
        'Con': 'More complex implementation',
        'Best for': 'Production systems like Twitter',
    },
}
for strategy, details in fan_out_strategies.items():
    print(f'{strategy}:')
    for k, v in details.items(): print(f'  {k}: {v}')
    print()

Erreurs courantes lors des entretiens de conception de systèmes

Évitez ces erreurs fréquentes qui peuvent faire dérailler les entretiens de conception de systèmes :

  • Passer directement aux solutions : dessiner des boîtes avant d’avoir clarifié les exigences révèle de mauvaises habitudes d’ingénierie
  • Pas d’estimation : concevoir sans connaître l’échelle relève de la conjecture
  • Surconception : concevoir pour 1 milliard d’utilisateurs alors que l’énoncé en prévoit 10 000 fait perdre du temps pendant l’entretien
  • Pas de compromis : chaque choix comporte des avantages et des inconvénients ; ne pas les mentionner révèle une compréhension superficielle
  • Silence : les examinateurs doivent entendre votre raisonnement ; explicitez vos décisions au fur et à mesure que vous les prenez
# Checklist: before you stop talking, verify you covered:
checklist = [
    '[ ] Asked clarifying questions about scale and constraints',
    '[ ] Made capacity estimates (RPS, storage, bandwidth)',
    '[ ] Defined the API surface clearly',
    '[ ] Described the data model and storage choices',
    '[ ] Drew a high-level architecture with named components',
    '[ ] Identified the main bottleneck and proposed a solution',
    '[ ] Discussed at least one trade-off explicitly',
    '[ ] Verified the design meets the stated requirements',
]
for item in checklist:
    print(item)

Vérification rapide

Testez votre compréhension des concepts de structures de données et d’algorithmes — préparation aux entretiens de programmation abordés dans cette leçon.

Récapitulatif de la leçon

Dans cette leçon, vous avez appris : le cadre RADIO structure les entretiens de conception de systèmes autour des Exigences, de l’API, du Modèle de données, de l’Infrastructure et de l’Optimisation, qu’il faut toujours clarifier les exigences fonctionnelles et non fonctionnelles et estimer la capacité avant de proposer une conception, et qu’il faut expliciter les compromis — chaque choix de conception présente des avantages et des inconvénients que les examinateurs s’attendent à vous voir formuler. Ensuite, nous verrons comment choisir entre les moteurs de stockage SQL et NoSQL en fonction des modes d’accès, de la cohérence et de la montée en charge.

Questions Fréquemment Posées

La leçon « Cadre d’entretien de conception de systèmes » est-elle gratuite ?

Oui — le texte complet de « Cadre d’entretien de conception de systèmes » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DSA Interview Prep, passe à CoddyKit PRO. Le cours DSA Interview Prep comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Cadre d’entretien de conception de systèmes » ?

Parcourez le cadre RADIO en cinq étapes (Requirements, API, Data, Infrastructure, Optimise) et entraînez-vous à l’appliquer à un raccourcisseur d’URL. Tu pratiques DSA Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer DSA Interview Prep ?

Aucune expérience préalable n'est requise. DSA Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Cadre d’entretien de conception de systèmes » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon DSA Interview Prep ?

Oui. Chaque leçon DSA Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Cadre d’entretien de conception de systèmes
  2. Stockage de données évolutif : SQL ou NoSQL
  3. Mise en cache, CDN et équilibrage de charge
  4. Concevoir un limiteur de débit et un fil Twitter
← Retour à DSA Interview Prep