The Map That Made Me Rethink My System Design Approach
I stumbled upon a visual "System Design Topic Map" from ByteByteGo that stopped me mid-scroll. As someone who's built products, led teams, and spent too m...
10 Aug 2025

I stumbled upon a visual "System Design Topic Map" from ByteByteGo that stopped me mid-scroll. As someone who's built products, led teams, and spent too many late nights debugging scaling issues, this map felt like a cheat sheet for everything I wish I'd had years ago.
Why It Resonated
When you work on real-world systems, you realize "system design" isn't one skill. It's an entire ecosystem: application design, communication protocols, scalability patterns, security, data layers, and infrastructure.
Looking at the map, I immediately recalled moments from my career:
- The time I learned why rate limiting isn't optional — after a DDoS attempt on one of our APIs.
- When our "quick prototype" grew into a monolith so big that migrating to microservices felt like open-heart surgery.
- The painful week I spent implementing leader election in a distributed system, wishing I'd studied it sooner.
How the Map Breaks Down
- Core Concepts and Application Layer — patterns like Domain-Driven Design and Clean Architecture give you a mental framework. Without them, you're adding features without structure.
- Network and Communication — if your system talks to anything else (and it does), you need to know your protocols. HTTP, gRPC, message queues (AMQP), real-time communication. Mastering real-time is where you unlock great user experiences.
- Scalability and Reliability — sharding, caching, auto-scaling. You don't just learn these. You earn them through production incidents.
- Security and Observability — I've seen brilliant products fail because security was an afterthought. And without monitoring and logging, you're flying blind.
- Infrastructure and Deployment — Kubernetes or a single EC2 instance, the principles of Infrastructure as Code and CI/CD keep you sane.
- Data Layer — choosing between SQL, NoSQL, and NewSQL isn't just a tech decision. It shapes your product's capabilities and limitations.
Deep Dive: Real-Time Communication — 3 Strategies I've Used
Real-time communication looks simple on the surface. In reality, the right approach depends on your requirements, scale, and infrastructure.
1. Long Polling
The client sends a request. The server holds the connection open until new data is available or a timeout occurs. Once the server responds, the client immediately sends another request.
I've used long polling when WebSockets weren't an option for our infrastructure, or for quick "real-time-ish" updates where SSE and WebSockets felt like overkill.
Tips from experience:
- Keep timeouts reasonable (20-30 seconds).
- Batch multiple updates in one response when possible.
- Always implement retries for dropped connections.
async function longPoll() {
try {
const res = await fetch('/updates');
const data = await res.json();
console.log('New data:', data);
} catch (err) {
console.error('Polling error:', err);
} finally {
longPoll();
}
}
longPoll();
2. Server-Sent Events (SSE)
A one-way channel from server to client over HTTP. The server streams updates continuously over a single, long-lived connection.
I use SSE for live dashboards where only the server pushes updates. Notifications, feed updates, status changes — anything where the client doesn't need to send frequent messages back.
Benefit: Lightweight, simpler than WebSockets, built-in reconnection in most browsers.
Cost: One-way only. No sending data from client to server over the same channel.
const events = new EventSource('/stream');
events.onmessage = (event) => {
console.log('New message:', event.data);
};
events.onerror = (err) => {
console.error('SSE error:', err);
};
Server-side (Node.js with Express):
const express = require('express');
const app = express();
app.get('/stream', (req, res) => {
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
const sendMessage = (msg) => {
res.write(`data: ${JSON.stringify(msg)}\n\n`);
};
sendMessage({ message: 'Connected to SSE' });
const interval = setInterval(() => {
sendMessage({ time: new Date().toISOString() });
}, 2000);
req.on('close', () => {
clearInterval(interval);
});
});
app.listen(3000, () => console.log('SSE server running on port 3000'));
3. WebSockets
Full-duplex (two-way) persistent connection between client and server. No repeated HTTP overhead. Messages go both ways in real-time.
I use WebSockets for chat apps, multiplayer games, collaborative editing — anywhere latency matters and messages flow in both directions.
Best practices:
- Use ping/pong heartbeats to detect dropped connections.
- Authenticate at connection handshake.
- Monitor message rates to prevent abuse.
const socket = new WebSocket('ws://localhost:3000');
socket.onopen = () => {
console.log('Connected to WebSocket');
socket.send(JSON.stringify({ type: 'hello', message: 'Hi server!' }));
};
socket.onmessage = (event) => {
console.log('Received:', event.data);
};
Server-side (Node.js with ws):
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3000 });
wss.on('connection', (ws) => {
console.log('New client connected');
ws.send(JSON.stringify({ message: 'Welcome to WebSocket server' }));
ws.on('message', (message) => {
console.log('Received from client:', message);
ws.send(JSON.stringify({ echo: message }));
});
ws.on('close', () => {
console.log('Client disconnected');
});
});
console.log('WebSocket server running on ws://localhost:3000');
How I Choose Between Them
- Long Polling — works everywhere, simple to implement, but least efficient. Good enough for low-frequency updates.
- SSE — great for server-to-client streams with minimal complexity. My default for dashboards and notifications.
- WebSockets — the right choice for full interactive, two-way communication at scale. More infrastructure overhead.
How I Use This Map
I've bookmarked it as a self-audit tool. Before starting any project, I run through each category:
- Have we picked the right architecture pattern?
- Is our communication protocol the best fit?
- Do we have a scaling strategy from day one?
- Is security baked in, not bolted on?
If you're building anything beyond a hobby app, keep a similar map on hand. It's like having a senior architect reviewing your decisions — without the meetings.