Phase 2: Networking Foundations + L4 (Days 31–60)
Phase Goal: Understand how network communication actually works — from socket to TLS — by building it in Go. This is the knowledge gap between "I know TCP/IP" and "I understand what my network team deals with."
Week 5: Networking Concepts + TCP Basics (Days 31–37)
Why this week matters: You've approved budget for CDNs, WAFs, and load balancers. This week explains what they actually do at the wire level.
Day 31 — The OSI model in practice
- Why: When an incident happens at L3 vs L7, the debugging approach is completely different. Knowing where your tools operate is essential for incident command
- Topic: OSI layers 1–7 (physical → application), where Go code lives (L4–L7), what happens between
net.Dialand data delivery, packet encapsulation - Exercise: Write a Go program that traces what happens when you connect to
example.com:80: DNS resolution (net.LookupHost), TCP connection (net.Dial), raw HTTP/1.0 request (conn.Write), read response. Log every step with timing.
Day 32 — TCP fundamentals
- Why: TCP is the transport for HTTP, TLS, gRPC, and almost everything your services use. SYN floods, slowloris, and connection exhaustion all target TCP
- Topic: TCP 3-way handshake (SYN→SYN-ACK→ACK), connection states, sequence numbers, acknowledgements, flow control, congestion control (conceptual),
TIME_WAIT - Exercise: Write a TCP echo server (
net.Listen+net.Accept). Handle 100 concurrent clients. After each echo, log: local addr, remote addr, bytes exchanged. Observenetstat -anwhile running.
Day 33 — TCP server patterns
- Why: Every microservice you run is a TCP server underneath. Understanding accept loops, connection limits, and timeouts helps you set sensible
http.Serverconfigs - Topic: Accept loop, per-connection goroutine, connection lifecycle,
SetDeadline,SetReadDeadline,SetWriteDeadline, half-close (CloseWrite) - Exercise: Build a hardened TCP server: max 1000 concurrent connections (use
sync/atomiccounter), 30s idle timeout per connection, log connections by state (new/active/closing). Test with 2000 simultaneous clients.
Day 34 — UDP
- Why: DNS, QUIC, DTLS, and monitoring protocols (StatsD, syslog UDP) use UDP. Understanding it helps you evaluate QUIC-based CDN products
- Topic: UDP vs TCP (no handshake, no ordering, no guaranteed delivery),
net.PacketConn,net.UDPConn, MTU, why UDP is used for DDoS amplification - Exercise: Build a UDP-based statsd-like metrics receiver: listen on UDP, parse
metric.name:value|typepackets, aggregate (count/gauge/timer), print summary every 5s. Handle 10k packets/sec.
Day 35 — I/O patterns for networking
- Why:
io.Copy,io.TeeReader,io.LimitReader— these are how Go efficiently moves bytes between connections. Knowing them explains how proxies work - Topic:
io.Copy,io.TeeReader,io.LimitReader,io.MultiWriter,bufioover connections, zero-copy concepts - Exercise: Build a TCP traffic mirror: for each client connection, forward to upstream AND copy all traffic to a "tap" (write to a file). Client sees normal responses. Use
io.TeeReader. No buffering of full request.
Day 36 — Connection pools
- Why: Connection pooling is why your services don't exhaust upstream connection limits.
http.Transportdoes this automatically — but security proxies need custom pools - Topic: Pool design (Get/Put/Close), idle timeout, max pool size, health checking,
sync.Poolvs explicit pool, when connections go stale - Exercise: Build a generic TCP connection pool:
Get(addr) (net.Conn, error),Put(conn),Close(). Idle connections expire after 30s. Max 10 connections per address. Test with 50 concurrent goroutines.
Day 37 — DNS in Go
- Why: DNS is the first hop in every request. DNS failures cause incidents. DNS is also an amplification attack vector
- Topic:
net.LookupHost,net.LookupMX,net.LookupTXT,net.Resolver(custom), DNS round-robin, TTL, negative caching - Exercise: Build a DNS-aware connection dialer: resolve hostname to IPs (potentially multiple), try each in order, cache results with TTL, fall back to next IP on connection failure. Measure DNS resolution latency separately.
Week 5 Mini Project: TCP Proxy with Traffic Inspector
- Build a transparent TCP proxy:
client → proxy → upstream - Features:
- Bidirectional forwarding (using goroutines +
io.Copy) - Traffic tap: log all bytes in hex to a file (via
io.TeeReader) - Connection tracking: active connections, total bytes in/out (via
expvar) - Per-connection timeout (30s idle)
- Connection pool to upstream (max 20 connections)
- Graceful shutdown: drain existing connections
- Bidirectional forwarding (using goroutines +
- Key packages:
net,io,sync,sync/atomic,context,expvar,time - Engineer Takeaway: A TCP proxy is the foundation of load balancers, WAFs, and security gateways. Cloudflare, Fastly, and your internal proxies all start here.
Week 6: TLS & Secure Transport (Days 38–44)
Why this week matters: TLS is invisible when it works and catastrophic when it breaks. Cert expiry causes outages. mTLS is how zero-trust networks authenticate services. You need to understand this deeply.
Day 38 — TLS handshake
- Why: Every HTTPS request, every gRPC call, every mTLS service mesh connection starts with a TLS handshake. Knowing what fails (cert mismatch, expired cert, cipher mismatch) helps you triage incidents
- Topic: TLS 1.2 vs 1.3 handshake steps, certificate purpose, cipher suites, SNI (Server Name Indication), ALPN, session resumption
- Exercise: Write a TLS client that connects to
example.com:443usingcrypto/tls. Print: TLS version, cipher suite, server cert chain (subject, issuer, expiry, SANs). Detect if cert expires in < 30 days.
Day 39 — TLS server in Go
- Why: Every internal service should use TLS. Understanding
tls.Configoptions is how you set security policy - Topic:
tls.Listen,tls.Config,MinVersion(require TLS 1.2+), cipher suite selection,InsecureSkipVerify(never in prod — understand why), certificate loading - Exercise: Build a TLS echo server using a self-signed cert. Client verifies the cert. Force TLS 1.3 only. Log the cipher suite and TLS version for each connection. Test with
openssl s_client.
Day 40 — Certificate generation in Go
- Why: Internal services and dev environments need certs. Knowing how to generate them in Go means you can automate cert provisioning without
opensslscripts - Topic:
crypto/x509,crypto/rsa,crypto/ecdsa,encoding/pem,x509.Certificatefields,x509.CreateCertificate, self-signed vs CA-signed - Exercise: Write a Go program that generates: (1) root CA cert + key, (2) server cert signed by CA, (3) client cert signed by CA. Save all as PEM files. Verify the chain.
Day 41 — Mutual TLS (mTLS)
- Why: mTLS is the foundation of zero-trust architectures. Service meshes (Istio, Linkerd) and internal APIs use it. You'll configure and debug mTLS in these products
- Topic:
tls.RequireAndVerifyClientCert,ClientCAspool, client cert validation,VerifyPeerCertificatehook, mTLS vs API keys - Exercise: Build an mTLS server: require client cert, verify it's signed by your CA, extract the client's Common Name (use it as identity), reject unknown clients. Build a matching client.
Day 42 — Hashing & HMAC
- Why: Request signing (AWS SigV4, webhook validation), token integrity, and content fingerprinting all use HMAC. You'll implement and review these in real systems
- Topic:
crypto/sha256,crypto/sha512,crypto/hmac,crypto/subtle.ConstantTimeCompare(timing attack prevention), when to use which hash - Exercise: Build a webhook request signing system: server signs outgoing webhooks with HMAC-SHA256. Client verifies. Demonstrate why
bytes.Equalis wrong (timing attack) andsubtle.ConstantTimeCompareis right.
Day 43 — Symmetric encryption
- Why: Session tokens, at-rest encryption, and encrypted logs all use AES. Understanding AES-GCM vs AES-CBC helps you make (and review) crypto choices
- Topic:
crypto/aes,cipher.NewGCM, nonce/IV requirements,crypto/randfor nonce generation, authenticated encryption (AEAD), why GCM > CBC for new designs - Exercise: Build an encrypted audit log: each log entry is AES-256-GCM encrypted with a per-entry nonce. Include a timestamp in the plaintext. Decrypt and verify on read. The key comes from an env var.
Day 44 — Asymmetric crypto & token signing
- Why: JWT, OAuth tokens, and mTLS certs all use asymmetric crypto. When a design says "sign tokens with ECDSA," you'll know what that means and why ECDSA P-256 > RSA 2048 for this
- Topic:
crypto/ecdsa,crypto/elliptic(P-256), digital signatures, sign/verify,crypto/randfor key generation, why ECDSA for tokens - Exercise: Build a token system:
Sign(claims map[string]string) (token string, err error)using ECDSA P-256.Verify(token string) (claims map[string]string, err error). Tokens expire after 1 hour. No JWT library.
Week 6 Mini Project: mTLS Service Gateway
- Build a gateway that enforces mTLS between clients and a backend
- Features:
- Generate CA, server cert, and client certs in Go (at startup if not present)
- Require client cert; extract identity from Common Name
- Forward authenticated requests to upstream HTTP server
- Inject
X-Client-Identityheader with the client's CN - Reject unauthorized clients with
403 - Hot-reload certs on
SIGHUPwithout dropping connections - Signed session tokens (ECDSA) issued after successful mTLS auth
- Key packages:
crypto/tls,crypto/x509,crypto/ecdsa,net/http,os/signal - Engineer Takeaway: This is the core of a zero-trust service-to-service auth system. Istio, SPIFFE, and mutual TLS service meshes all implement this pattern. You've now built it from scratch.
Week 7: L4 Load Balancing & Resilience (Days 45–51)
Why this week matters: Load balancers sit in front of every production service. Understanding how they work helps you evaluate AWS NLB vs ALB vs HAProxy vs your own solution.
Day 45 — Load balancing algorithms
- Why: Round-robin, least-connections, and consistent hashing have very different behavior under load. Knowing the trade-offs helps you make the right choice for your traffic pattern
- Topic: Round-robin (simple, stateless), weighted round-robin, least connections (stateful, better for variable-cost requests), random, power of two choices
- Exercise: Implement all 4 algorithms. Simulate 10,000 requests with variable request durations. Measure load distribution across 5 backends. Which has best distribution? Which has lowest average latency?
Day 46 — Backend health checking
- Why: A load balancer that sends traffic to dead backends is worse than no load balancer. Health checking design is a real production decision
- Topic: Active health checks (periodic dial), passive health checks (track errors in-flight), health check interval, failure threshold, recovery threshold, circuit breaker concept
- Exercise: Build an active health checker: every 5s, TCP-connect to each backend. Track consecutive failures. Remove backend after 3 failures. Re-add after 2 successes. Emit events when state changes.
Day 47 — Connection draining
- Why: When you deploy a new version or scale down, connections to old backends must finish gracefully. This is what "connection draining" in your load balancer settings does
- Topic: Drain state machine (active → draining → closed), in-flight connection tracking, drain timeout, force-close after timeout
- Exercise: Add drain support to your load balancer: mark backend as draining (stop sending new connections), wait for existing connections to finish (30s timeout), then close. Test by draining while 50 connections are active.
Day 48 — TCP load balancer (L4)
- Why: AWS NLB, HAProxy in TCP mode, and Cloudflare's Spectrum are L4 load balancers. Understanding why you'd use L4 vs L7 helps you spec the right tool
- Topic: L4 vs L7 load balancing trade-offs, no HTTP parsing at L4, connection-level decisions only, performance advantage of L4
- Exercise: Assemble a complete L4 TCP load balancer: accept client connections, pick backend (least-connections), open a pooled connection to backend, bidirectional proxy. Handle backend failure mid-connection.
Day 49 — Rate limiting at L4
- Why: Connection-level rate limiting is the first line of DDoS defense. Your network team deploys this before traffic even reaches the application
- Topic: Per-IP connection limits, global connection limits, token bucket for connection rate,
sync/atomicfor counters - Exercise: Add L4 rate limiting to the load balancer: max 100 concurrent connections per source IP, max 1000 global. New connections beyond limits are immediately rejected (RST). Track and expose metrics.
Day 50 — Observability at L4
- Why: Without metrics, you can't answer "how is the load balancer performing?" during an incident
- Topic:
expvarcounters for: connections accepted/rejected/active, bytes in/out per backend, health check results, connection duration histogram - Exercise: Add full observability to the load balancer. Expose via
/debug/vars. Build a simple/statsendpoint that returns a human-readable summary of backend health and connection counts.
Day 51 — Resilience patterns
- Why: Circuit breakers, retries, and timeouts are how services stay up when dependencies are flaky. You'll add them to every service that calls another service
- Topic: Circuit breaker (closed/open/half-open states), retry with exponential backoff, timeout propagation via context, idempotency requirements for retries
- Exercise: Implement a circuit breaker wrapping a backend connection. Trips after 5 consecutive failures. Half-opens after 30s. Build retry logic with jitter: 3 retries, exponential backoff (100ms, 200ms, 400ms), only retry on network errors.
Week 7 Mini Project: Production L4 Load Balancer
- Build a complete L4 TCP load balancer:
- Multiple backends (round-robin + least-connections, switchable)
- Active health checking (TCP probe every 5s)
- Connection draining (graceful backend removal)
- Per-IP and global connection rate limiting
- Circuit breaker per backend
- mTLS client connections (from Week 6)
- Full observability:
/debug/vars,/stats,/health - Graceful shutdown with drain
- Key packages:
net,crypto/tls,sync,sync/atomic,context,expvar,time - Engineer Takeaway: AWS NLB bills per LCU-hour. You now understand what an LCU is, what the LB is doing for that money, and what each of its settings changes.
Week 8: Review + Phase 2 Consolidation (Days 52–60)
Why this week matters: Consolidation is where knowledge becomes instinct. Slower pace, deeper understanding.
Day 52 — TCP internals: what goes wrong
- Why:
TIME_WAIT,CLOSE_WAIT, andFIN_WAITare states you'll see during production incidents. Understanding them prevents misdiagnosis - Topic: TCP state machine deep dive,
TIME_WAIT(normal, 2*MSL),CLOSE_WAIT(application bug),FIN_WAIT_2,SO_LINGER,SO_REUSEADDR - Exercise: Deliberately create
CLOSE_WAITsockets (server doesn't callconn.Close()). Observe withnetstat. Fix the bug. ObserveTIME_WAITstates after graceful close. Why don't they cause problems?
Day 53 — Binary protocol design
- Why: Internal services sometimes use binary protocols for performance (gRPC uses protobuf, Kafka uses its own wire format). Understanding framing helps you review protocol proposals
- Topic:
encoding/binary, length-prefix framing, fixed-header + variable-body, endianness, versioning - Exercise: Design a binary protocol for a key-value store:
[1B version][1B opcode][4B key-len][key][4B value-len][value]. Build encoder/decoder. Build a test server and client. Benchmark vs JSON.
Day 54 — TLS certificate rotation
- Why: Cert expiry is a common incident cause. Zero-downtime cert rotation requires
GetCertificatecallback, not just loading cert at startup - Topic:
tls.Config.GetCertificate, atomic cert swap, cert caching, cert expiry monitoring, OCSP stapling concept - Exercise: Build a TLS server that hot-reloads its certificate: watch for a new cert file (poll
os.Stat), swap atomically usingsync/atomic+unsafe.Pointer(orsync.RWMutex). No connections dropped on reload.
Day 55 — SNI routing
- Why: SNI lets one IP/port serve multiple domains with different certs and backends. This is how Cloudflare, Nginx, and most CDNs work
- Topic: SNI (Server Name Indication),
tls.Config.GetCertificatereceivesClientHelloInfo.ServerName, routing table - Exercise: Build an SNI router: one listener, multiple backends. Route based on the TLS SNI hostname to different upstream servers. Each hostname gets its own cert. Test with 3 different hostnames.
Day 56 — Connection multiplexing concepts
- Why: HTTP/2 multiplexes many requests over one TCP connection. gRPC does the same. Understanding this helps you size connection pools correctly
- Topic: HTTP/2 streams, framing, stream ID, flow control, HEADERS + DATA frames (conceptual), why H2 needs fewer connections than H1
- Exercise: Build a simple request multiplexer over TCP: multiple logical "streams" over one connection, identified by a 4-byte stream ID in each frame. Demultiplex on the other end.
Day 57 — Error propagation in network code
- Why: Network errors are different from application errors. Knowing
net.Error,os.ErrDeadlineExceeded, and temporary vs permanent errors helps you write reliable retry logic - Topic:
net.Errorinterface (Timeout(),Temporary()),io.EOFvsio.ErrUnexpectedEOF,os.ErrDeadlineExceeded,syscall.ECONNRESET, error wrapping - Exercise: Build an error classifier for network code: categorize every error from
net.Connoperations into: timeout, connection reset, EOF (clean close), unexpected EOF (peer crash), other. Log each with appropriate severity.
Day 58 — Race conditions in network servers
- Why: Race conditions in network code cause data corruption and security vulnerabilities.
-raceis mandatory. Knowing common patterns helps you catch them in review - Topic: Common races: closing connection from multiple goroutines, concurrent map access in connection state, deadline race with data read
- Exercise: Take the Week 5 TCP proxy. Run
go test -race. Find and fix all races. Document each race: what was the bug? What was the fix? What could have gone wrong in production?
Day 59 — Benchmark the full L4 stack
- Why: "It's fast enough" needs a number. Knowing how to measure throughput and latency for your proxy is how you set SLOs
- Topic: Load testing with goroutines (no external tools), measuring: connections/sec, throughput (MB/s), p50/p95/p99 latency, max concurrent connections
- Exercise: Write a load test for the Week 7 load balancer: 1000 concurrent clients, each making 100 TCP round-trips. Measure and print: total requests, RPS, p50/p95/p99 latency, error rate.
Day 60 — Phase 2 Review
- Audit all Phase 2 projects for: goroutine leaks, missing
defer conn.Close(), improper error handling - Run
go test -race ./...on all projects - Document: what would break first under 10x traffic? What would you change?
- Engineer Takeaway: You now understand L4 networking deeply enough to design a solution, debug it during an incident, and review other people's designs.
Week 8 Mini Project: Secure TCP Gateway
- Combine all Phase 2 work into a secure TCP gateway:
- mTLS client termination (from Week 6)
- L4 load balancing to multiple backends (from Week 7)
- Per-IP rate limiting
- Circuit breaker per backend
- SNI routing (different backends by hostname)
- Health checking with expiry
- Full observability (
/debug/vars,/stats,/health) - Graceful shutdown with cert hot-reload on SIGHUP
- Key packages:
net,crypto/tls,crypto/x509,sync,sync/atomic,expvar - Engineer Takeaway: This is roughly what Cloudflare Spectrum does for TCP proxying. You've built it.