Frontend Labs
⋯

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.Dial and 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. Observe netstat -an while 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.Server configs
  • 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/atomic counter), 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|type packets, 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, bufio over 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.Transport does this automatically — but security proxies need custom pools
  • Topic: Pool design (Get/Put/Close), idle timeout, max pool size, health checking, sync.Pool vs 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
  • 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:443 using crypto/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.Config options 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 openssl scripts
  • Topic: crypto/x509, crypto/rsa, crypto/ecdsa, encoding/pem, x509.Certificate fields, 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, ClientCAs pool, client cert validation, VerifyPeerCertificate hook, 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.Equal is wrong (timing attack) and subtle.ConstantTimeCompare is 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/rand for 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/rand for 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-Identity header with the client's CN
    • Reject unauthorized clients with 403
    • Hot-reload certs on SIGHUP without 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/atomic for 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: expvar counters 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 /stats endpoint 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, and FIN_WAIT are 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_WAIT sockets (server doesn't call conn.Close()). Observe with netstat. Fix the bug. Observe TIME_WAIT states 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 GetCertificate callback, 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 using sync/atomic + unsafe.Pointer (or sync.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.GetCertificate receives ClientHelloInfo.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.Error interface (Timeout(), Temporary()), io.EOF vs io.ErrUnexpectedEOF, os.ErrDeadlineExceeded, syscall.ECONNRESET, error wrapping
  • Exercise: Build an error classifier for network code: categorize every error from net.Conn operations 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. -race is 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.

Generated from golang-90-day-plan.md · 8 Oct 2026 16:36