In modern cloud architecture, “upstream” services constantly need to talk to “downstream” APIs. For our AI Interviewer application, we recently faced a challenge: how to securely and efficiently call the metering endpoint on our authentication gateway that handles billing.
While the solution might seem straightforward, the path to getting it right involved avoiding some common networking pitfalls.
The Dilemma: Public Latency vs. Private Complexity
When connecting two services within AWS, you generally have two “obvious” but flawed choices:
Option 1: The Public Route
You call the endpoint using its public URL (e.g., https://meter.example.com/bill).
- The Problem: Traffic leaves the AWS backbone and traverses the public internet unnecessarily. Furthermore, if a developer accidentally misses the
httpsprotocol, sensitive API keys could be leaked over the wire.
Option 2: The Direct IP Route
You whitelist the upstream Security Group and call the instance directly via its private IP (e.g., http://x.y.z.w:PORT/bill).
- The Problem: This is brittle. It requires both services to be in the same VPC, and it forces the application to bind to
0.0.0.0rather than127.0.0.1. This weakens our security posture by bypassing NGINX, which usually acts as our protective gatekeeper.
The Elegant Middle Ground: Private Hosted Zones
We wanted the best of both worlds: the clean, domain-based approach of Option 1, but the security and speed of Option 2. The solution is an AWS Route 53 Private Hosted Zone (PHZ).
A PHZ acts as an internal DNS server that only exists within your specified VPC. When your application looks up meter.example.com, Route 53 returns a private IP instead of a public one.
Step-by-Step Implementation
1. Create the Private Hosted Zone
First, we tell Route 53 to manage the domain internally for our specific VPC.
aws route53 create-hosted-zone \
--name meter.example.com \
--vpc VPCRegion=us-west-2,VPCId=vpc-xxx \
--caller-reference $(date +%s) \
--hosted-zone-config Comment="Internal API routing",PrivateZone=true
2. Map the Domain to a Private IP
Next, we create an “A Record” that points our domain name to the internal private IP of our gateway server.
aws route53 change-resource-record-sets \
--hosted-zone-id /hostedzone/Z01165483IVUF0VMOL2KT \
--change-batch '{
"Changes": [{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "meter.example.com",
"Type": "A",
"TTL": 300,
"ResourceRecords": [{"Value": "x.y.z.w"}]
}
}]
}'
The Result: Split-Horizon DNS in Action
Now, when our upstream AI Interviewer performs a DNS lookup, it no longer sees the public internet. It stays entirely within the AWS fabric.
Verification via nslookup:
$ nslookup meter.example.com
Non-authoritative answer:
Name: meter.example.com
Address: x.y.z.w <-- Our Internal IP!
Why This Matters
- Zero Latency: Traffic never leaves the data center.
- Security by Default: Even if we use standard protocols, the data stays on a private network.
- Maintainability: We can keep our NGINX configuration exactly as it is, maintaining a consistent security posture across public and private requests.
By leveraging Private Hosted Zones, we’ve built a system that is as easy to use as a public API but as secure as a private LAN.