Stage 3 · Build
HTTP, HTTP/2 & gRPC
Debugging APIs in Production
curl, httpie, grpcurl, and distributed tracing with OpenTelemetry.
curl Mastery
curl is the most important debugging tool for HTTP APIs. It gives you full control over every aspect of the request — headers, body, method, TLS, proxies, and timing.
# Verbose output (shows headers, TLS handshake)
curl -v https://api.example.com/users
# Custom method and headers
curl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"name": "Alice", "email": "alice@example.com"}'
# Follow redirects
curl -L https://example.com/old-path
# Show timing breakdown
curl -w "DNS: %{time_namelookup}s\nConnect: %{time_connect}s\nTLS: %{time_appconnect}s\nFirst byte: %{time_starttransfer}s\nTotal: %{time_total}s\n" \
-o /dev/null -s https://api.example.com
# Send cookies
curl -b cookies.txt -c cookies.txt https://api.example.com/loginThe -w flag with timing variables shows exactly where time is spent. DNS lookup, TCP connect, TLS handshake, time to first byte, and total time. This helps identify whether slowness is DNS, network, or server-side.
Create a scripts/api/ directory with shell scripts for common API calls. Use environment variables for tokens and base URLs. This makes debugging reproducible and shareable with your team.
httpie for Human-Friendly Debugging
# Install httpie
brew install httpie
# GET request (simpler than curl)
http GET https://api.example.com/users
# POST with JSON (no Content-Type header needed)
http POST https://api.example.com/users \
name=Alice email=alice@example.com
# Authentication
http --auth=bearer:$TOKEN https://api.example.com/me
# Session persistence (saves cookies, headers)
http --session=mysession https://api.example.com/login \
user=admin password=secret
# Download with progress
http --download https://api.example.com/file.ziphttpie automatically formats JSON, handles authentication, and provides colored output. It is designed for interactive use — when you want to quickly test an API without remembering curl flags.
grpcurl for gRPC Services
# List all services
grpcurl -plaintext localhost:50051 list
# List methods in a service
grpcurl -plaintext localhost:50051 list users.UserService
# Call a method
grpcurl -plaintext -d '{"id": 123}' \
localhost:50051 users.UserService/GetUser
# With metadata (headers)
grpcurl -plaintext \
-H "Authorization: Bearer $TOKEN" \
-d '{"id": 123}' \
localhost:50051 users.UserService/GetUser
# With TLS
grpcurl -ca ca.pem \
-d '{"id": 123}' \
api.example.com:443 users.UserService/GetUsergrpcurl requires server reflection or .proto files. Enable reflection in development. In production, pass the .proto files with -import-path. grpcurl supports all four gRPC patterns: unary, server streaming, client streaming, and bidi streaming.
Distributed Tracing
Distributed tracing follows a request as it flows through multiple services. Each service creates a span (a unit of work). Spans are grouped into a trace (the full request path). OpenTelemetry is the standard for generating and exporting traces.
# Add trace context to curl request
curl -H "traceparent: 00-abc123def456-span789-01" \
https://api.example.com/orders
# The trace header format:
# version-trace_id-parent_span_id-trace_flags
# Check Jaeger/Zipkin for traces
curl "http://localhost:16686/api/traces?service=api-gateway" | jq
# OpenTelemetry collector config
# Receives spans from services and exports to Jaeger/TempoWhen a request fails, distributed tracing shows you exactly which service failed and how long each step took. The trace ID lets you correlate logs across services. Without tracing, debugging microservices is guesswork.
API Gateway Debugging
# Check gateway logs
kubectl -n ingress-nginx logs -l app.kubernetes.io/name=ingress-nginx --tail=50
# Check rate limiting headers
curl -v https://api.example.com/users 2>&1 | grep -i "x-ratelimit"
# Check backend health
curl http://backend-service:8080/health
# Verify routing rules
kubectl describe ingress my-ingress
# Check certificate at gateway
echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | \
openssl x509 -noout -subject -datesAPI gateways add a layer between clients and services. When debugging, check: is the gateway receiving the request? Is it routing correctly? Is the backend healthy? Is TLS terminating at the gateway?
Watch for: proxy headers being overwritten (X-Forwarded-For), request body size limits, timeout mismatches (gateway timeout < backend processing time), and WebSocket upgrade failures through non-WebSocket-aware proxies.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.