Real-World Case Studies
Learn from how the world’s largest tech companies built and evolved their microservices architectures.Learning Objectives:
- Analyze Netflix’s pioneering microservices journey
- Understand Uber’s domain-oriented architecture
- Learn Amazon’s two-pizza team approach
- Study Spotify’s squad model and service design
- Extract actionable lessons for your own systems
Netflix: The Pioneer
Evolution Journey
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ NETFLIX ARCHITECTURE EVOLUTION │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 2007: MONOLITH ERA │
│ ───────────────────────── │
│ • Single Java monolith │
│ • Oracle database │
│ • Datacenter deployment │
│ • DVD rental + early streaming │
│ │
│ ↓ Major outage (database corruption) │
│ │
│ 2009-2012: MIGRATION TO CLOUD │
│ ───────────────────────────────── │
│ • Move to AWS │
│ • Break apart monolith │
│ • Adopt microservices │
│ • Build internal tools (Simian Army, Zuul, Eureka) │
│ │
│ ↓ Scaling to 100M+ subscribers │
│ │
│ 2015-2020: MATURE MICROSERVICES │
│ ────────────────────────────────── │
│ • 700+ microservices │
│ • 100,000+ AWS instances │
│ • Multiple regions globally │
│ • Advanced chaos engineering │
│ │
│ 2020+: FEDERATION & GRAPHQL │
│ ──────────────────────────────── │
│ • GraphQL Federation │
│ • Studio applications │
│ • Content delivery optimization │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Key Architecture Decisions
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ NETFLIX KEY PATTERNS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. API GATEWAY (Zuul) │
│ ───────────────────── │
│ • Single entry point │
│ • Dynamic routing │
│ • Load balancing │
│ • Authentication │
│ │
│ Client ──▶ Zuul ──▶ Microservices │
│ │ │
│ ├──▶ User Service │
│ ├──▶ Content Service │
│ └──▶ Recommendation Service │
│ │
│ 2. SERVICE DISCOVERY (Eureka) │
│ ──────────────────────────── │
│ • Self-registration │
│ • Health checking │
│ • Client-side load balancing │
│ │
│ Service A ──register──▶ Eureka ◀──discover── Service B │
│ │
│ 3. CIRCUIT BREAKER (Hystrix) │
│ ────────────────────────── │
│ • Fail fast │
│ • Fallback responses │
│ • Bulkhead isolation │
│ • Real-time metrics │
│ │
│ 4. CONFIGURATION (Archaius) │
│ ────────────────────────── │
│ • Dynamic properties │
│ • No restart needed │
│ • Feature flags │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Netflix’s Personalization Architecture
Copy
// Simplified view of Netflix's recommendation system
/*
┌────────────────────────────────────────────────────────────────────────────┐
│ PERSONALIZATION PIPELINE │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ User │ │ Context │ │ Content │ │
│ │ Profile │ │ Service │ │ Catalog │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └───────────────────┼───────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Personalization│ │
│ │ Engine │ │
│ └────────┬────────┘ │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌───────────────┐ ┌───────────────┐ ┌───────────────┐ │
│ │ Row Selection │ │ Row Ranking │ │ Artwork │ │
│ │ Algorithm │ │ Algorithm │ │ Personalization│ │
│ └───────────────┘ └───────────────┘ └───────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
Key Design Principles:
- Every page element is personalized
- A/B testing for all algorithms
- Precomputed recommendations (offline)
- Real-time adjustments (online)
- Graceful degradation to popular content
*/
class PersonalizationService {
async getHomePage(userId, context) {
// Get user data with circuit breaker
const userProfile = await this.circuitBreaker.execute(
'user-service',
() => this.userService.getProfile(userId),
() => this.getDefaultProfile() // Fallback
);
// Get personalized rows
const rows = await Promise.all([
this.getRow('continue-watching', userId, context),
this.getRow('trending-now', userId, context),
this.getRow('because-you-watched', userId, context),
this.getRow('top-picks', userId, context)
]);
// Rank and filter rows
const rankedRows = this.rankRows(rows, userProfile);
// Select personalized artwork for each title
const rowsWithArtwork = await this.personalizeArtwork(rankedRows, userProfile);
return {
rows: rowsWithArtwork,
experimentIds: this.getActiveExperiments(userId)
};
}
async getRow(rowType, userId, context) {
const cacheKey = `row:${rowType}:${userId}`;
// Check precomputed cache
let row = await this.cache.get(cacheKey);
if (!row) {
// Compute on-demand (rare)
row = await this.computeRow(rowType, userId, context);
await this.cache.set(cacheKey, row, 3600);
}
// Real-time adjustments
row = this.applyContextAdjustments(row, context);
return row;
}
}
Lessons from Netflix
Build for Failure
Assume everything will fail. Build systems that degrade gracefully.
Automate Everything
Deploy, scale, test, recover - all automated. Humans make mistakes under pressure.
Chaos Engineering
Break things on purpose to build confidence. Netflix invented Chaos Monkey.
Observability
You can’t fix what you can’t see. Invest heavily in monitoring and tracing.
Uber: Domain-Oriented Microservices
Architecture Overview
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ UBER'S DOMAIN-ORIENTED ARCHITECTURE │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────────┐ │
│ │ API Gateway │ │
│ │ (Edge Service) │ │
│ └─────────┬──────────┘ │
│ │ │
│ ┌─────────────────────────┼─────────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ RIDERS │ │ DRIVERS │ │ EATS │ │
│ │ DOMAIN │ │ DOMAIN │ │ DOMAIN │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ ┌─────┴─────┐ ┌─────┴─────┐ ┌─────┴─────┐ │
│ │ • Rider │ │ • Driver │ │ • Orders │ │
│ │ Service │ │ Service │ │ • Menu │ │
│ │ • Trips │ │ • Earnings│ │ • Delivery│ │
│ │ • Ratings │ │ • Schedule│ │ • Ratings │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ │
│ ════════════════════════════════════════════════════════════════════════ │
│ SHARED PLATFORM SERVICES │
│ ──────────────────────────────────────────────────────────────────────── │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Mapping │ │ Pricing │ │ Dispatch │ │ Payments │ │ Comms │ │
│ │ │ │ │ │ │ │ │ │ (SMS/Push)│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ════════════════════════════════════════════════════════════════════════ │
│ INFRASTRUCTURE LAYER │
│ ──────────────────────────────────────────────────────────────────────── │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Schemaless│ │ Ringpop │ │ Cherami │ │ Cadence │ │ Peloton │ │
│ │ (MySQL) │ │ (Routing)│ │ (Queues) │ │(Workflow)│ │ (Deploy) │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Key Insight: Domain-oriented microservices, not just technical decomposition.
Services are grouped by business domain, not by technical function.
Uber’s Dispatch System
Copy
// Simplified Uber dispatch architecture
/*
DISPATCH CHALLENGE:
- Match riders with drivers in real-time
- Optimize for ETA, driver earnings, rider satisfaction
- Handle 15+ million trips per day
- Sub-second matching requirements
*/
class DispatchService {
constructor() {
this.supplyIndex = new GeospatialIndex(); // Real-time driver locations
this.demandQueue = new PriorityQueue(); // Rider requests
this.matchingEngine = new MatchingEngine();
}
// Driver sends location update (every 4 seconds)
async updateDriverLocation(driverId, location, status) {
// Update in-memory geospatial index
if (status === 'available') {
await this.supplyIndex.upsert(driverId, location);
} else {
await this.supplyIndex.remove(driverId);
}
// Persist to storage asynchronously
this.eventBus.publish('driver.location.updated', {
driverId,
location,
status,
timestamp: Date.now()
});
}
// Rider requests a trip
async requestTrip(riderId, pickup, destination) {
const request = {
id: generateId(),
riderId,
pickup,
destination,
requestedAt: Date.now(),
status: 'pending'
};
// Find nearby available drivers
const nearbyDrivers = await this.supplyIndex.findNearby(
pickup,
{ radiusKm: 5, limit: 20 }
);
if (nearbyDrivers.length === 0) {
return { status: 'no_drivers', surge: await this.getSurgeMultiplier(pickup) };
}
// Calculate ETAs for each driver
const driversWithETA = await Promise.all(
nearbyDrivers.map(async (driver) => ({
...driver,
eta: await this.mapService.getETA(driver.location, pickup),
score: await this.calculateMatchScore(driver, request)
}))
);
// Sort by match score
driversWithETA.sort((a, b) => b.score - a.score);
// Dispatch to best match
const bestDriver = driversWithETA[0];
const dispatch = await this.dispatchToDriver(bestDriver, request);
return dispatch;
}
async calculateMatchScore(driver, request) {
// Multi-factor scoring
const etaScore = 100 - (driver.eta / 60); // Prefer closer drivers
const ratingScore = driver.rating * 10; // Prefer higher rated
const acceptanceScore = driver.acceptanceRate * 50; // Prefer reliable
// Fairness factor (avoid always picking same driver)
const fairnessScore = 100 - Math.min(driver.tripsToday * 5, 50);
return etaScore + ratingScore + acceptanceScore + fairnessScore;
}
async dispatchToDriver(driver, request) {
// Create dispatch record
const dispatch = {
id: generateId(),
requestId: request.id,
driverId: driver.id,
status: 'dispatched',
dispatchedAt: Date.now(),
expiresAt: Date.now() + 15000 // 15 second window to accept
};
// Remove driver from available pool
await this.supplyIndex.remove(driver.id);
// Send push notification to driver
await this.notificationService.sendToDriver(driver.id, {
type: 'trip_request',
dispatch,
request
});
// Wait for response with timeout
return this.waitForAcceptance(dispatch);
}
async waitForAcceptance(dispatch) {
return new Promise((resolve) => {
const timeout = setTimeout(() => {
// Driver didn't respond - try next driver
resolve({ status: 'timeout', dispatch });
}, 15000);
this.on(`dispatch.${dispatch.id}.accepted`, () => {
clearTimeout(timeout);
resolve({ status: 'accepted', dispatch });
});
this.on(`dispatch.${dispatch.id}.declined`, () => {
clearTimeout(timeout);
resolve({ status: 'declined', dispatch });
});
});
}
}
Uber’s Migration Patterns
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ UBER'S MIGRATION APPROACH │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ STRANGLER FIG PATTERN │
│ ──────────────────────────── │
│ │
│ Phase 1: Identify bounded contexts │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ MONOLITH │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Riders │ │ Drivers │ │ Trips │ │ Payments│ │ Mapping │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ Phase 2: Extract one service at a time │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ MONOLITH │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Riders │ │ Drivers │ │ Trips │ │ Payments│ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Mapping Service │ ← Extracted │
│ └─────────────────┘ │
│ │
│ Phase 3: Continue extracting │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ SHRINKING MONOLITH │ │
│ │ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Riders │ │ Trips │ │ │
│ │ └─────────┘ └─────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Drivers │ │ Payments │ │ Mapping │ │ Pricing │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ KEY LEARNING: "Don't migrate data, migrate ownership" │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Lessons from Uber
Domain-Driven Design
Organize by business domain, not technical layers. Clear ownership boundaries.
Platform Approach
Build shared platforms (mapping, payments) used by all product teams.
Data Consistency
Accept eventual consistency. Design compensating transactions.
Observability
End-to-end tracing is critical. Uber built Jaeger for this.
Amazon: The Two-Pizza Team
Service-Oriented Architecture Origins
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ AMAZON'S SOA MANDATE (2002) │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ Jeff Bezos' famous mandate: │
│ │
│ 1. All teams will henceforth expose their data and functionality through │
│ service interfaces. │
│ │
│ 2. Teams must communicate with each other through these interfaces. │
│ │
│ 3. There will be no other form of interprocess communication allowed. │
│ │
│ 4. It doesn't matter what technology they use. │
│ │
│ 5. All service interfaces must be designed from the ground up to be │
│ externalizable. │
│ │
│ 6. Anyone who doesn't do this will be fired. │
│ │
│ This led to: │
│ • AWS being possible (externalized internal services) │
│ • Thousands of independent services │
│ • True service ownership │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Amazon’s Team Structure
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ TWO-PIZZA TEAM MODEL │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ PRINCIPLE: A team should be small enough to be fed by two pizzas │
│ (typically 6-10 people) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ TWO-PIZZA TEAM │ │
│ │ │ │
│ │ 👤👤👤👤👤👤 (6-10 people) │ │
│ │ ├── Engineers (4-6) │ │
│ │ ├── Product Manager (1) │ │
│ │ ├── TPM/Scrum Master (1) │ │
│ │ └── UX (0.5-1) │ │
│ │ │ │
│ │ OWNS: │ │
│ │ • 1-3 microservices │ │
│ │ • Full lifecycle (dev, test, deploy, operate) │ │
│ │ • On-call rotation │ │
│ │ • Business metrics │ │
│ │ │ │
│ │ AUTONOMY: │ │
│ │ • Choose tech stack │ │
│ │ • Define API contracts │ │
│ │ • Set deployment schedule │ │
│ │ • Manage technical debt │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ "You build it, you run it" - Werner Vogels │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Amazon’s Event-Driven Architecture
Copy
// Amazon's event-driven approach
/*
KEY PATTERN: Events as the source of truth
When you place an order on Amazon, this happens:
1. Order Service creates order
2. Publishes OrderPlaced event
3. Multiple services react independently:
- Inventory reserves stock
- Payment processes charge
- Shipping calculates delivery
- Recommendations updates models
- Email sends confirmation
*/
class OrderService {
async placeOrder(orderData) {
// Create order in database
const order = await this.repository.create({
...orderData,
status: 'pending',
orderId: generateOrderId()
});
// Publish event - other services react
await this.eventBridge.publish({
source: 'order-service',
detailType: 'OrderPlaced',
detail: {
orderId: order.orderId,
customerId: order.customerId,
items: order.items,
total: order.total,
shippingAddress: order.shippingAddress
}
});
// Return immediately - don't wait for downstream
return {
orderId: order.orderId,
status: 'pending',
message: 'Order received and being processed'
};
}
}
// Inventory Service reacts to order events
class InventoryService {
constructor() {
this.eventBridge.subscribe('OrderPlaced', this.handleOrderPlaced.bind(this));
}
async handleOrderPlaced(event) {
const { orderId, items } = event.detail;
try {
// Reserve inventory
for (const item of items) {
await this.reserveStock(item.productId, item.quantity, orderId);
}
// Publish success event
await this.eventBridge.publish({
source: 'inventory-service',
detailType: 'InventoryReserved',
detail: { orderId, items }
});
} catch (error) {
// Publish failure event
await this.eventBridge.publish({
source: 'inventory-service',
detailType: 'InventoryReservationFailed',
detail: { orderId, reason: error.message }
});
}
}
}
// Order Saga Coordinator (or choreography handles compensation)
class OrderSagaCoordinator {
constructor() {
this.eventBridge.subscribe('InventoryReservationFailed', this.handleInventoryFailure.bind(this));
this.eventBridge.subscribe('PaymentFailed', this.handlePaymentFailure.bind(this));
}
async handleInventoryFailure(event) {
const { orderId, reason } = event.detail;
// Cancel order
await this.orderService.updateStatus(orderId, 'cancelled', reason);
// Notify customer
await this.eventBridge.publish({
source: 'order-saga',
detailType: 'OrderCancelled',
detail: { orderId, reason: `Item unavailable: ${reason}` }
});
}
}
Spotify: Squad Model
Team Topology
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ SPOTIFY'S SQUAD MODEL │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ TRIBE (100-150 people) │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ SQUAD SQUAD SQUAD SQUAD │ │
│ │ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ │
│ │ │ 🎵 │ │ 🔍 │ │ 📱 │ │ 💳 │ │ │
│ │ │Play │ │Search│ │Mobile│ │Pay │ │ │
│ │ │Squad│ │Squad │ │Squad │ │Squad│ │ │
│ │ └─────┘ └─────┘ └─────┘ └─────┘ │ │
│ │ │ │ │ │ │ │
│ │ └────────────┴─────────────┴─────────────┘ │ │
│ │ │ │ │
│ │ TRIBE LEAD │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ CHAPTERS (Horizontal - same skill) │
│ ───────────────────────────────────── │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Backend Chapter │ Frontend Chapter │ QA Chapter │ │
│ │ 👤👤👤👤 │ 👤👤👤👤 │ 👤👤👤 │ │
│ │ (from all squads) │ (from all squads) │ (from all squads) │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ GUILDS (Voluntary - interest groups) │
│ ───────────────────────────────────── │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ Web Guild │ iOS Guild │ ML Guild │ Agile Guild │ │
│ │ 👤 👤 👤 │ 👤 👤 │ 👤 👤 👤 👤 │ 👤 👤 │ │
│ │ (across tribes) │ │ │ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
│ KEY INSIGHT: Squads are autonomous but aligned │
│ Chapters spread knowledge │
│ Guilds create communities of practice │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Spotify’s Backend Architecture
Copy
// Spotify's service patterns
/*
AUDIO STREAMING ARCHITECTURE:
- 400M+ monthly active users
- 80M+ tracks
- Personalized for each user
*/
class PlaybackService {
async startPlayback(userId, trackId, deviceId) {
// Get track metadata
const track = await this.trackService.getTrack(trackId);
// Check user's subscription
const subscription = await this.subscriptionService.get(userId);
// Determine audio quality based on subscription
const quality = this.determineQuality(subscription, deviceId);
// Get CDN URL for audio file
const audioUrl = await this.cdnService.getAudioUrl(trackId, quality);
// Record play start (for royalties, analytics)
await this.playService.recordPlay({
userId,
trackId,
deviceId,
quality,
startedAt: Date.now()
});
// Update user's playback state
await this.stateService.updatePlaybackState(userId, {
trackId,
deviceId,
playing: true,
position: 0
});
return {
trackId,
audioUrl,
quality,
metadata: track
};
}
}
// Content Delivery Optimization
class CDNService {
async getAudioUrl(trackId, quality) {
// Multi-CDN strategy for global delivery
const cdns = await this.getCDNsForTrack(trackId);
// Select best CDN based on:
// - User location
// - CDN health
// - Current load
const bestCDN = this.selectOptimalCDN(cdns);
// Generate signed URL
return this.generateSignedUrl(trackId, quality, bestCDN);
}
}
// Personalization (Discover Weekly, Daily Mix, etc.)
class RecommendationService {
async generateDiscoverWeekly(userId) {
// User taste profile (built from listening history)
const tasteProfile = await this.getTasteProfile(userId);
// Collaborative filtering (users with similar taste)
const collaborativeRecs = await this.collaborativeFilter(userId, tasteProfile);
// Content-based (similar audio features)
const contentRecs = await this.contentBasedFilter(tasteProfile);
// Blend recommendations
const blended = this.blendRecommendations([
{ source: 'collaborative', weight: 0.5, items: collaborativeRecs },
{ source: 'content', weight: 0.3, items: contentRecs },
{ source: 'release_radar', weight: 0.2, items: await this.getNewReleases(tasteProfile) }
]);
// Remove already played tracks
const filtered = await this.filterKnownTracks(userId, blended);
// Create playlist
return this.createPlaylist(userId, 'Discover Weekly', filtered.slice(0, 30));
}
}
Key Lessons Comparison
Copy
┌─────────────────────────────────────────────────────────────────────────────┐
│ LESSONS FROM TECH GIANTS │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ COMPANY │ KEY LESSON │ PATTERN │
│ ────────────┼────────────────────────────────┼─────────────────────────────│
│ │ │ │
│ Netflix │ Design for failure │ Chaos Engineering, │
│ │ Everything fails eventually │ Circuit Breakers, │
│ │ │ Graceful Degradation │
│ │ │ │
│ ────────────┼────────────────────────────────┼─────────────────────────────│
│ │ │ │
│ Uber │ Domain-oriented design │ Bounded Contexts, │
│ │ Organize by business, not tech │ Platform Services, │
│ │ │ Saga Pattern │
│ │ │ │
│ ────────────┼────────────────────────────────┼─────────────────────────────│
│ │ │ │
│ Amazon │ Service ownership │ Two-Pizza Teams, │
│ │ You build it, you run it │ Event-Driven, │
│ │ │ API Mandate │
│ │ │ │
│ ────────────┼────────────────────────────────┼─────────────────────────────│
│ │ │ │
│ Spotify │ Autonomous but aligned │ Squad Model, │
│ │ Balance autonomy with cohesion │ Chapters/Guilds, │
│ │ │ Trunk-Based Dev │
│ │ │ │
└─────────────────────────────────────────────────────────────────────────────┘
Interview Questions
Q1: How did Netflix migrate from monolith to microservices?
Q1: How did Netflix migrate from monolith to microservices?
Answer:Netflix’s migration took 7+ years (2009-2016):
- Trigger: Major database outage in 2008
- Cloud-first: Migrated to AWS
- Incremental extraction: Started with non-critical services
- Built tooling: Eureka, Hystrix, Zuul, Ribbon
- Chaos engineering: Validated resilience continuously
- API Gateway for routing
- Client-side load balancing
- Circuit breakers everywhere
- Service registry for discovery
Q2: What is Amazon's Two-Pizza Team?
Q2: What is Amazon's Two-Pizza Team?
Answer:A team small enough to be fed by two pizzas (6-10 people).Characteristics:
- Full ownership of 1-3 services
- End-to-end responsibility (build, test, deploy, operate)
- Autonomous decision making
- Direct accountability for business metrics
- Fast decision making
- Clear ownership
- Reduced communication overhead
- Motivation through ownership
Q3: How does Uber handle dispatch at scale?
Q3: How does Uber handle dispatch at scale?
Answer:Uber’s dispatch handles 15M+ trips/day:
- Real-time location tracking
- Drivers send GPS every 4 seconds
- Geospatial index in memory
- Supply-demand matching
- Find nearby drivers
- Calculate ETAs using map service
- Score by ETA, rating, fairness
- Dispatch with timeout
- Push notification to driver
- 15 second response window
- Cascade to next driver if declined
- Event-driven updates
- All state changes are events
- Enables real-time tracking
Q4: What is Spotify's Squad Model?
Q4: What is Spotify's Squad Model?
Answer:Organizational structure for autonomy with alignment:Squads (6-12 people):
- Cross-functional mini-startup
- Owns feature end-to-end
- Autonomous decision making
- Related squads grouped together
- Shared mission
- 100-150 people max
- Same skill across squads
- Knowledge sharing
- Technical growth
- Voluntary communities
- Cross-tribe learning
Chapter Summary
Key Takeaways:
- Netflix: Design for failure with chaos engineering
- Uber: Domain-oriented architecture with platform services
- Amazon: Small autonomous teams with full ownership
- Spotify: Squad model balances autonomy and alignment
- All companies evolved incrementally, not big-bang migrations
- Invest heavily in tooling and observability