DSA Interview Prep · Lektion

Ramverk för systemdesignintervjuer

Gå igenom RADIO-ramverket i fem steg (Requirements, API, Data, Infrastructure, Optimise) och öva på att tillämpa det på en URL-förkortare.

Lektion 1 av 413 steg

Ramverk för systemdesignintervjuer är en gratis lektion i DSA Interview Prep på CoddyKit. Detta är lektion 1 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för DSA Interview Prep, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i DSA Interview Prep innehåller totalt 4 lektioner.

Varför systemdesign är viktigt i intervjuer

Systemdesignintervjuer testar din förmåga att tänka i stor skala — hur skulle du utforma Twitter, YouTube eller en URL-förkortare för miljarder användare? Till skillnad från kodningsproblem med ett enda korrekt svar är systemdesign öppen: du måste göra avvägningar och motivera dem. På senior- och staffnivå ägnas 30–45 minuter uteslutande åt detta moment.

Intervjuare bedömer om du kan förtydliga krav, uppskatta belastning, föreslå en övergripande arkitektur, gå in på djupet i viktiga komponenter och diskutera avvägningar — samtidigt som du kommunicerar tydligt. Ett strukturerat ramverk hindrar dig från att sväva ut och ser till att du täcker alla kritiska aspekter.

# 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)

Översikt över RADIO-ramverket

RADIO-ramverket ger en återanvändbar struktur i fem steg för alla systemdesignintervjuer:

  • R — Krav: funktionella och icke-funktionella
  • A — API-design: vilka operationer exponerar systemet?
  • D — Datamodell: vilka data lagras och hur?
  • I — Infrastruktur: övergripande komponenter (servrar, köer, cachar)
  • O — Optimera: flaskhalsar, cachning, sharding, replikering

Gå alltid igenom dessa steg i ordning, men återvänd till tidigare steg och förfina dem när nya insikter uppstår. Lägg ungefär lika mycket tid på varje fas. Hoppa aldrig direkt till att rita rutor utan att först förtydliga kraven.

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')

Steg R: Förtydliga kraven

Börja aldrig designa utan att först förtydliga kraven. Fråga om funktionella krav (vad systemet gör) och icke-funktionella krav (skala, fördröjning, tillgänglighet). För en URL-förkortare:

  • Funktionella: förkorta en URL, omdirigera till den ursprungliga URL:en och eventuellt stödja anpassade alias och utgångsdatum
  • Icke-funktionella: hur många URL:er per dag? Är systemet läs- eller skrivintensivt? Krav på tillgänglighet (99.9 % jämfört med 99.99 %)? Acceptabel fördröjning?

Att uttryckligen ange antaganden visar mognad. Intervjuare ger ofta avsiktligt vaga specifikationer för att se om du ställer rätt frågor. Två minuters förtydliganden sparar dig från att designa fel system.

# 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)

Steg R: Överslagsberäkning

Efter kraven ska du uppskatta kapaciteten. Det visar att du kan resonera om skala innan du föreslår lösningar. Viktiga tal att härleda är: antal begäranden per sekund (RPS), lagringsutrymme som behövs per dag och år, bandbredd samt minne för cachning.

Använd runda tal och gör fria approximationer. Intervjuare bryr sig om storleksordningen, inte om exakta siffror. Exempel för en URL-förkortare: 100M skrivningar/dag ÷ 86400 ≈ 1160 skrivningar/sekund. 10B läsningar/dag ÷ 86400 ≈ 115K läsningar/sekund. Varje URL-post ≈ 500 byte: 100M × 500B = 50 GB/dag, 18 TB/år.

# 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}')

Steg A: API-design

Definiera API-ytan — de operationer som systemet exponerar för klienter och interna tjänster. Ange tydligt HTTP-metod, endpoint-sökväg, request-parametrar och response-format. Detta förankrar resten av designen: allt annat finns till för att implementera dessa API:er.

För en URL-förkortare är de två centrala API:erna: (1) POST /shorten för att skapa en kort URL, (2) GET /{alias} för att omdirigera. Valfritt: DELETE /{alias} för att ta bort, GET /{alias}/stats för analys. Ange svarsstatuskoder (201 Created, 301 Redirect, 404 Not Found).

# 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()

Steg D: Datamodell

Datamodellen definierar vad du lagrar och hur. Identifiera de centrala entiteterna och deras attribut. För en URL-förkortare: en urls-tabell med alias (primärnyckel), long_url, created_at, expires_at och user_id. En valfri tabell för clicks kan användas för analys.

Det är avgörande att välja rätt lagringstyp: relationsdatabas för strukturerade data med komplexa frågor; key-value store (Redis, DynamoDB) för aliasuppslagningar i O(1) vid stor skala; objektlagring (S3) för stora blobbar. För en URL-förkortare är ett key-value store med alias som nyckel idealiskt för läsningar, med en relationsdatabas för skrivningar och hantering.

# 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')

Steg I: Infrastruktur på hög nivå

Skissa den övergripande infrastrukturen: vilka servrar som hanterar vilka ansvarsområden, hur data flödar mellan komponenterna och vilka externa tjänster som används. För en URL-förkortare i stor skala:

  • Lastbalanserare: fördelar trafiken till repliker av skriv- och lästjänster
  • Skrivtjänst: genererar alias, validerar unikhet, skriver till databasen och invaliderar cachen
  • Läs-/omdirigeringstjänst: kontrollerar Redis-cachen först och går vidare till databasen vid cachemiss
  • Relationsdatabas: auktoritativ källa (med läsrepliker)
  • Redis-kluster: cachar populära URL-mappningar för läsningar på under en millisekund
# 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)')

Steg O: Optimera och hantera flaskhalsar

Optimeringsfasen hanterar flaskhalsar och skalar systemet. För en URL-förkortare är de viktigaste frågorna: fördröjning vid omdirigering (placera Redis nära användarna med CDN- eller edge-cachar), unikhet för alias i stor skala (använd en central ticket-server eller en hash med kollisionsdetektering) och flaskhalsar vid databasskrivning (batchskrivningar eller asynkrona skrivningar med en kö).

Diskutera avvägningarna uttryckligen: 301-omdirigeringar minskar serverbelastningen men försämrar analysnoggrannheten; 302-omdirigeringar kan spåras men ökar fördröjningen. Cachning med lång giltighetstid minskar databasbelastningen men innebär risk för inaktuella URL:er. Att visa att du förstår dessa avvägningar signalerar tänkande på seniornivå.

# 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()

Aliasgenerering: Base62-kodning

En central teknisk detalj i URL-förkortare är hur korta, unika alias genereras. Standardmetoden är att använda ett autoinkrementerande heltals-ID från databasen och koda det i Base62 (siffrorna 0-9, bokstäverna a-z, A-Z). En Base62-sträng med 7 tecken kan representera 62^7 ≈ 3,5 biljoner unika URL:er — tillräckligt för årtionden med 100M per dag.

Detta är kollisionsfritt (varje ID är unikt) och ger korta, URL-säkra strängar. Mappningen från ID till alias är deterministisk och reversibel. Nackdelen är att sekventiella ID:n skapar förutsägbara alias (ett säkerhetsproblem). Blanda Base62-alfabetet eller använd en räknarförskjutning för att göra dem mindre förutsägbara.

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}')

Tillämpa RADIO på designen av ett Twitter-flöde

Låt oss kort tillämpa RADIO på designen av ett Twitter-liknande nyhetsflöde för att visa att ramverket kan generaliseras:

  • R: Användare publicerar tweets, följer andra och ser ett flöde med tweets från personer de följer. Skala: 300M användare, 500M tweets/dag, flödet måste läsas in på <2s.
  • A: POST /tweets, GET /feed, GET /timeline/{user_id}
  • D: tweets-tabell (id, user_id, content, created_at); follows-tabell (follower_id, followee_id); flödescache per användare
  • I: Fan-out-tjänst skriver nya tweets till följares flöden (förberäknat); Cassandra för skrivintensiva follow/tweet-tabeller; Redis för flödescachar
# 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()

Vanliga misstag i systemdesignintervjuer

Undvik dessa vanliga misstag som kan få systemdesignintervjuer att spåra ur:

  • Hoppa direkt till lösningar: att rita rutor innan ni har klargjort kraven signalerar bristande ingenjörsmässighet
  • Inga uppskattningar: att utforma en lösning utan att känna till omfattningen blir rena gissningar
  • Överdimensionering: att utforma för 1 miljard användare när uppgiften säger 10 000 slösar bort intervjutid
  • Inga avvägningar: varje val har för- och nackdelar; om ni inte nämner dem tyder det på en ytlig förståelse
  • Tystnad: intervjuare behöver höra hur ni resonerar; redogör för besluten medan ni fattar dem
# 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)

Snabbtest

Testa er förståelse av begreppen Data Structures & Algorithms — Coding Interview Prep från den här lektionen.

Sammanfattning av lektionen

I den här lektionen lärde ni er: RADIO-ramverket strukturerar systemdesignintervjuer i Requirements, API, Data Model, Infrastructure och Optimise, att alltid klargöra funktionella och icke-funktionella krav samt göra kapacitetsuppskattningar innan ni föreslår en lösning, och att uttryckligen diskutera avvägningar — varje designval har för- och nackdelar som intervjuare förväntar sig att ni kan förklara. Nästa steg är att utforska hur ni väljer mellan SQL- och NoSQL-lagringsmotorer utifrån åtkomstmönster, konsistens och skala.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
30
Lektioner
120

Vanliga frågor

Är lektionen ”Ramverk för systemdesignintervjuer” gratis?

Ja – du kan läsa vilka 3 lektioner som helst i lärvägen DSA Interview Prep, inklusive ”Ramverk för systemdesignintervjuer”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i DSA Interview Prep innehåller totalt 4 lektioner.

Vad lär jag mig i ”Ramverk för systemdesignintervjuer”?

Gå igenom RADIO-ramverket i fem steg (Requirements, API, Data, Infrastructure, Optimise) och öva på att tillämpa det på en URL-förkortare. Ni övar på DSA Interview Prep med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig DSA Interview Prep?

Du behöver inga förkunskaper. Utbildningen i DSA Interview Prep på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.

Hur lång tid tar lektionen ”Ramverk för systemdesignintervjuer”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här DSA Interview Prep-lektionen?

Ja. Varje DSA Interview Prep-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Ramverk för systemdesignintervjuer
  2. Skalbar datalagring: SQL eller NoSQL
  3. Caching, CDN:er och lastbalansering
  4. Designa Rate Limiter och Twitter Feed
← Tillbaka till DSA Interview Prep