High-performance Go REST API for IP geolocation, ASN, and subnet lookups. Queries 5 free sources in parallel and merges results via consensus voting.
Client ──▶ Netpulse ──▶ ip-api.com
──▶ ipwhois.io
──▶ ipinfo.io
──▶ db-ip.com
──▶ ipgeolocation.io (optional)
│
◀────┘
vote + median merge
│
Client ◀── JSON response ───┘
- Request fans out to all sources concurrently
- Results collected with a configurable timeout (default 10s)
- String fields (country, city, org) — majority vote
- Coordinates — median (throws out outliers)
- ASN — most common answer
- Response shows which sources succeeded and which failed
- Go 1.25 — backend language
- Huma v2 — OpenAPI-first framework, spec generated from Go types
- chi — router
- BigCache — in-memory cache with zero GC pauses
- gzip — response compression via sync.Pool
- cert-manager + HAProxy — TLS and ingress on Kubernetes
| Source | Limit | API key |
|---|---|---|
| ip-api.com | 45 req/min | no |
| ipwhois.io | unlimited | no |
| ipinfo.io | 50k/month | no |
| db-ip.com | unlimited | no |
| ipgeolocation.io | 1k/day | optional |
git clone https://github.com/xdearboy/netpulse.git
cd netpulse
go run cmd/server/main.goServer starts on http://localhost:8080, Swagger UI at /docs.
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/ip/{ip} |
IP geolocation |
| GET | /api/v1/asn/{asn} |
ASN info |
| GET | /api/v1/subnet/{cidr} |
Subnet info |
| POST | /api/v1/batch |
Batch lookup |
| GET | /health |
Source status + metrics |
| GET | /metrics |
Request stats, cache ratio |
| GET | /docs |
Swagger UI |
| GET | /openapi.json |
OpenAPI spec |
curl http://localhost:8080/api/v1/ip/8.8.8.8{
"ip_address": "8.8.8.8",
"type": "IPv4",
"country": "US",
"city": "Mountain View",
"latitude": 37.4056,
"longitude": -122.0775,
"isp": "Google LLC",
"asn": 15169,
"sources_used": ["ip-api.com", "ipwhois.io", "ipapi.is"],
"query_time": "245ms"
}| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
Server port |
AGGREGATOR_TIMEOUT |
10s |
Source query timeout |
CACHE_TTL |
10m |
In-memory cache TTL |
RATE_LIMIT |
100 |
Requests per window per IP |
RATE_LIMIT_WINDOW |
1m |
Rate limit window |
BATCH_MAX_SIZE |
50 |
Max items per batch request |
IPGEOLOCATION_API_KEY |
— | Optional key for ipgeolocation.io |
go test ./... -vdocker build -t netpulse .
docker run -p 8080:8080 netpulsekubectl apply -k deploy/Requires: cert-manager, HAProxy ingress controller.
make build # compile
make test # run tests with race detector
make run # start locally
make docker # build image
make deploy # apply k8s manifests
make logs # tail pod logsGitHub Actions pipeline in .github/workflows/ci.yaml:
- test — vet + test on every push/PR
- build-and-push — Docker build, push to GHCR
- deploy — kubectl apply + rollout on self-hosted K3s runner
See CONTRIBUTING.md for development setup and guidelines.