Networking Fundamentals: The Guide for Developers
You don't need a CCNA to ship reliable services, but you do need the core ideas. This is the map: DNS, TCP, TLS, proxies, and CDNs, minus the jargon.
Key takeaways
- Every request walks the same pipeline.
- DNS resolves the name, TCP opens a connection, TLS secures it, proxies and load balancers route it, and an origin or CDN serves it.
- When something breaks, check each stage in order with dig, curl -v, ss and openssl s_client, and the failing layer usually names itself.
On this page
Networking for developers comes down to one pipeline: resolve the name (DNS), open a connection (TCP), secure it (TLS), route it (proxy or load balancer), then serve it (origin or CDN). Most "mysterious" bugs live in one stage: a slow first request is DNS, a hang is a firewall, a certificate warning is TLS, a 502 is a proxy.
Verified against
curl 8.23.0 and OpenSSL 4.1.0, against the curl man page, the OpenSSL s_client docs, RFC 9293 (TCP) and RFC 9846 (TLS 1.3, published July 2026, obsoleting RFC 8446). Checked October 2026.
One command that shows the whole pipeline
Before reading about each layer, look at all of them at once. curl -w prints how long each stage took:
$ curl -s -o /dev/null https://example.com -w \
'dns=%{time_namelookup} tcp=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n'
dns=0.012 tcp=0.031 tls=0.068 ttfb=0.142 total=0.143
The numbers (an illustrative run) are cumulative seconds since the start, so subtract neighbours: here DNS took 12 ms, the TCP handshake 19 ms, TLS 37 ms, and the server spent 74 ms before the first byte. If dns is large, look at resolvers. If ttfb dominates, the network is fine and the app is slow. That one line ends a lot of arguments.
Names: DNS
Before anything connects, the name has to become an IP address. Resolvers cache answers for the record's TTL, which is why a changed record can take minutes or hours to reach everyone. How DNS works covers the lookup chain; ask the resolver directly with dig:
$ dig +noall +answer +comments api.example.com A
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4127
api.example.com. 300 IN A 203.0.113.10
$ dig @1.1.1.1 api.example.com A +short
203.0.113.10
status: NXDOMAIN means the name doesn't exist; SERVFAIL means the resolver couldn't get an answer, often a DNSSEC or upstream failure. Comparing your default resolver with a public one tells you whether the problem is local. On Linux hosts, DNS troubleshooting with resolvectl and dig goes further.
Connections: TCP and UDP
TCP, specified in RFC 9293, is reliable and ordered: a three-way handshake, retransmission, flow control. It carries the web, APIs and databases. UDP sends datagrams with no handshake or delivery guarantee, which suits DNS, video, games and QUIC, the transport under HTTP/3. Which to pick is in TCP vs UDP.
Two connection failures look alike but mean different things. Connection refused is fast: the host answered with a reset because nothing listens on that port. Timed out is slow: packets vanish, almost always a firewall or security group dropping them. Check what is actually listening:
$ ss -ltnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 4096 127.0.0.1:8080 0.0.0.0:* users:(("app",pid=812,fd=7))
An app bound to 127.0.0.1 is reachable only from the same machine, which is the most common "works locally, refused remotely" cause. Bind to 0.0.0.0 (or the right interface) and check the host firewall; iptables vs nftables explains which one your distro uses. For CIDR maths on security groups and subnets, the CIDR and subnet calculator shows the network, broadcast, mask and usable hosts for any block.
Security: the TLS handshake
The padlock is a negotiation. Client and server agree on keys and the client verifies the certificate chain and hostname before any application data flows. TLS 1.3 does this in one round trip. The step-by-step is in how the TLS handshake works, which pairs with the response-side controls in HTTP security headers. Inspect what a server actually presents:
$ openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
subject=CN=example.com
issuer=C=US, O=Let's Encrypt, CN=R11
notBefore=Oct 1 00:00:00 2026 GMT
notAfter=Dec 30 23:59:59 2026 GMT
-servername sends SNI. Leave it off and a server hosting many sites may return its default certificate, which then "doesn't match" and sends you chasing the wrong problem.
Getting to the app: proxies and load balancing
Real traffic rarely hits your app directly. A reverse proxy terminates TLS, routes and buffers, set up in how to set up an Nginx reverse proxy. A load balancer spreads requests across backends using an algorithm, compared in load balancing algorithms explained. The three terms are untangled in proxy vs reverse proxy vs load balancer.
The status code tells you which side failed. A 502 Bad Gateway means the proxy reached out and got garbage or a refused connection from the backend. A 504 Gateway Timeout means the backend accepted but didn't answer before the proxy's timeout. In both cases the proxy works and the backend doesn't; on Kubernetes, fixing ingress 502 and 504 errors walks the checks.
Speed at the edge: CDNs
A CDN serves cached copies from locations near the user, cutting latency and origin load. What is a CDN covers the model; CDN cache invalidation strategies covers keeping it fresh. When users see stale content, compare response headers such as Age and Cache-Control between the CDN hostname and the origin with curl -sI.
The error strings, by layer
| Error you see | Layer | Usual cause | First check |
|---|---|---|---|
curl: (6) Could not resolve host | DNS | Typo, missing record, broken resolver | dig name +short against two resolvers |
curl: (7) Failed to connect ... Connection refused | TCP | Nothing listening, or bound to localhost | ss -ltnp on the server |
curl: (28) Connection timed out | TCP / firewall | Security group or firewall dropping packets | Rules for that port and source CIDR |
curl: (60) SSL certificate problem: unable to get local issuer certificate | TLS | Server omits intermediate cert, or private CA | openssl s_client -showcerts |
502 Bad Gateway / 504 Gateway Timeout | Proxy / backend | Backend down, wrong port, too slow | Proxy error log, backend health |
Where this breaks
The pipeline model assumes a plain client-to-server path. Corporate proxies, VPNs and service meshes add hops that terminate TLS or rewrite DNS, so curl from your laptop and from inside the cluster can disagree; always test from where the failing client runs. HTTP/3 runs over QUIC on UDP, so TCP tools like ss -t won't show those connections. And curl -w timings are a single sample: measure several times before blaming a layer.
Questions people ask
What networking concepts should every developer know?
Know the request pipeline and which layer owns each symptom: DNS turns names into addresses, TCP or UDP carries the bytes, TLS encrypts and authenticates, reverse proxies and load balancers route, and CDNs cache at the edge. Add CIDR notation for reading firewall rules, and four tools: dig, curl -v, ss and openssl s_client. That covers most production debugging.
What is the difference between connection refused and connection timed out?
Connection refused arrives immediately: the host is reachable but nothing listens on that port, or the service only listens on 127.0.0.1, so the kernel replies with a reset. Connection timed out takes seconds: packets are silently dropped, usually by a firewall, security group or wrong route. Refused points at the service; timed out points at the network path.
How do I find which layer is slowing down a request?
Run curl -s -o /dev/null -w with time_namelookup, time_connect, time_appconnect, time_starttransfer and time_total. Each is cumulative, so subtract consecutive values to get DNS, TCP handshake, TLS handshake and server think time. A large DNS gap points to resolvers; a large first-byte gap means the network is fine and the application is slow.
The call we'd make
Learn the request path once and networking stops being magic. You don't need every RFC; you need to know which layer owns which symptom and which command inspects it. Start with DNS and TLS, the two behind most "it's slow" and "it's broken" reports, keep the curl -w one-liner in your shell history, then go deeper on proxies and CDNs as traffic grows. Read the linked guides in request-path order and the whole stack clicks into place.
Sources
Cite this article
Kiril Urbonas (2026). Networking Fundamentals: The Guide for Developers. DevOpsNess. Updated 2026-10-31. https://www.devopsness.com/blog/networking-fundamentals-guide
[Networking Fundamentals: The Guide for Developers](https://www.devopsness.com/blog/networking-fundamentals-guide) (Kiril Urbonas, DevOpsNess, updated 2026-10-31)
More from Infrastructure
Explore more articles in this category
Terraform Plan Wants to Recreate Your Production Database? Read This First
The plan says -/+ next to your RDS instance and one attribute ends in "forces replacement". Why it happens, how to undo it without data loss, and the CI gate that stops it reaching apply.
How to Stop Anyone From Deleting Your Production Database
GitLab lost six hours of data to one command on the wrong host. Linear lost five hours to one TRUNCATE CASCADE in a reviewed migration. The six guardrails that make that kind of mistake hard to make and cheap to recover from.
Kubelet Won't Start After Upgrading to Kubernetes 1.35? It's cgroup v1
Since Kubernetes 1.35 the kubelet refuses to start on cgroup v1 nodes by default. How to check every node in one command, the safe migration, and the temporary override with an expiry date.
You might have missed
Evergreen posts worth revisiting.