> your AI agent picks dependencies from memory; give it dated facts — try starlog.dev ↗ vet your agent's deps ↗ vibe-coding is fine. vibe-importing isn’t. — try starlog.dev ↗ vibe-importing isn’t fine ↗ your agent has never seen your private packages — try starlog.dev ↗ facts for private packages ↗ a linter for the dependencies your AI agent picks — try starlog.dev ↗ a linter for agent deps ↗

Back to Articles

httpdiff: The Minimalist's Guide to Comparing HTTP Servers Before Migration

[ View on GitHub ]

httpdiff: The Minimalist's Guide to Comparing HTTP Servers Before Migration

Hook

Before cutting over DNS to your new infrastructure, how confident are you that both servers return identical responses? Most teams discover differences in production.

Context

Server migrations are deceptively dangerous. You've provisioned new hardware, configured nginx identically, deployed the same application code—but will users see the same thing? The traditional approach involves manually curling endpoints, copying responses into files, and running diff commands. It's tedious, error-prone, and doesn't scale beyond a handful of spot checks.

The challenge intensifies with modern infrastructure. Load balancers sit between clients and origin servers. DNS changes take hours to propagate. You can't simply visit a URL to test the new server because your browser hits the old one. Setting up /etc/hosts entries for every engineer's laptop is brittle. What developers need is a surgical tool that can issue identical requests to two different servers—bypassing DNS, respecting Host headers, and immediately visualizing differences. This is precisely the gap httpdiff fills, with zero configuration and zero dependencies.

Technical Insight

URLs, Headers, Method

HTTP Request 1

HTTP Request 2

Response Headers & Body

Response Headers & Body

Identical

Differences Found

Green: Additions

Red: Deletions

Body Differences

CLI Flag Parser

Request Builder

Goroutine 1

Goroutine 2

Line-by-Line Differ

Terminal: Green Success

ANSI Colorizer

Terminal Output

Temp Files Writer

System architecture — auto-generated

httpdiff's architecture is deliberately minimal: parse flags, fire parallel HTTP requests, diff the results. The entire implementation lives in a single Go file leveraging only the standard library. This simplicity is its superpower—no YAML configs, no plugin systems, just a binary you can scp to a server and run immediately.

The tool's core operation executes two HTTP requests concurrently using goroutines, then performs a line-by-line comparison. Here's how you'd test a server migration in practice:

# Compare old server (old.example.com) vs new server (new.example.com)
# Both should respond identically to requests for www.example.com
httpdiff -H "Host: www.example.com" \
  http://old.example.com/api/users/123 \
  http://new.example.com/api/users/123

This command sends the same GET request to both servers with a custom Host header, critical when servers use virtual hosting or sit behind load balancers. The -H flag lets you set arbitrary headers—authentication tokens, custom user agents, or cache-control directives. You can also specify HTTP methods:

# Test POST endpoints during migration
httpdiff -m POST \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${TOKEN}" \
  https://staging-api.company.com/orders \
  https://prod-api.company.com/orders \
  -d '{"item": "widget", "quantity": 5}'

Under the hood, httpdiff uses Go's net/http client with a straightforward request construction pattern. It clones the request for both targets, executes them via goroutines, and waits for both to complete. This parallel execution matters: if one server is slow, you discover it immediately rather than waiting sequentially.

The diffing mechanism splits response headers and bodies into lines, then iterates comparing each line. When differences appear, httpdiff colorizes output using ANSI escape codes—green for lines unique to the second server, red for lines unique to the first. This visual distinction is surprisingly effective during rapid iteration. You don't need to parse diff syntax; differences jump off the screen.

For binary responses or large bodies where terminal output becomes unwieldy, httpdiff writes both responses to temporary files and prints their paths. You can then inspect them with dedicated diff tools, hex editors, or image viewers depending on content type. This escape hatch acknowledges that not everything belongs in a terminal.

One elegant detail: httpdiff preserves the entire HTTP exchange including status codes and headers. Many testing tools focus solely on response bodies, but headers often contain critical differences—cache control directives, security headers, cookie attributes. During migrations, these invisible differences cause subtle bugs that manifest only under production load.

Gotcha

httpdiff's simplicity becomes a limitation when responses contain non-deterministic data. Timestamps, request IDs, session tokens, and CSRF nonces will always differ, flooding your output with false positives. The tool has no concept of semantic equivalence—it can't ignore specific JSON fields or apply regular expressions to filter out expected differences.

Binary content and compressed responses pose similar challenges. While httpdiff writes binary bodies to files for external inspection, it doesn't understand content encodings. If your servers return gzipped responses, you'll be diffing compressed bytes rather than decompressed content. You'll need to either disable compression for testing or post-process the output files yourself.

The tool also lacks retry logic and timeout configuration. Network blips cause test failures even when servers are functionally identical. There's no support for following redirects independently—if your old server redirects to HTTPS but your new one doesn't, you can't easily test the final destination. Authentication flows requiring multiple round-trips or OAuth dances aren't supported. For complex API testing with assertions about response structure, status codes, or performance characteristics, you'll quickly outgrow httpdiff's capabilities.

Verdict

Use if: you're performing server migrations, testing load balancer configurations, or validating staging environments against production with deterministic endpoints. httpdiff excels at quick manual verification and can be scripted into CI pipelines for smoke tests. Its zero-dependency design makes it ideal for deployment to bastion hosts or locked-down production environments where installing comprehensive testing frameworks is forbidden. Skip if: you need to handle non-deterministic responses, require complex assertion logic, or want automated regression testing with detailed reporting. For those scenarios, invest in proper API testing frameworks like Postman collections with Newman, or programming language-specific tools like REST-assured or httpx with custom comparison logic that understands your domain.