Cloud Architecture·8 min read·

nginx as an API Gateway, Not a Cloud Product

Use nginx on an edge VPS as your API gateway: TLS, routing, auth headers, body limits, and rate caps without buying a managed API gateway SKU.

NB

Netbay Cloud Team

Netbay Engineering

On this page

An API gateway is a set of jobs, not a SKU. Terminate TLS, pick an upstream from the Host or the path, reject oversized bodies, attach a request id, rate-limit abusive clients, and refuse to proxy to Redis. nginx already does those jobs. Buying a managed gateway product adds a control plane, a bill, and a failure domain you do not operate. On a VPS fleet in Lucknow, a dedicated edge node running nginx is the gateway. The APIs behind it stay private to RFC1918 or firewalled public IPs.

What the Edge Is Allowed to Do

Keep policy at the edge dumb and fast. nginx should not run business rules. It should:

  • Terminate TLS 1.2/1.3 and HTTP/2
  • Route /v1/orders to the orders upstream and /v1/billing to the billing upstream
  • Cap body size so a 400MB JSON POST cannot fill High-Speed SSD on an app node
  • Rate-limit by IP or by API key hash
  • Inject X-Request-Id if the client did not send one
  • Block direct access to admin locations from the world

Authn can be a header check or auth_request to a tiny local service. Authz stays in the app. If you start writing Lua that knows about GST slabs, you are no longer operating a gateway; you are operating a second application in a language your on-call does not want to debug at 03:00.

nginx
upstream orders {
    server 10.0.0.21:8000 max_fails=3 fail_timeout=10s;
    keepalive 16;
}
upstream billing {
    server 10.0.0.22:8000 max_fails=3 fail_timeout=10s;
    keepalive 16;
}

limit_req_zone $binary_remote_addr zone=api_ip:10m rate=30r/s;
limit_req_status 429;

server {
    listen 443 ssl http2;
    server_name api.example.com;
    client_max_body_size 1m;
    proxy_read_timeout 8s;

    location /v1/orders/ {
        limit_req zone=api_ip burst=60 nodelay;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Request-Id $request_id;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://orders;
    }
}

proxy_read_timeout is an architecture number. Eight seconds is a statement that the request path is not allowed to wait for a partner. Workers exist for the rest. fail_timeout plus a second VPS in the upstream is node death handling, not a cluster product.

Auth Request, Not a Vendor SDK

If every route needs a bearer token, auth_request keeps JWT verification off the app hot path when you want a single choke point, or you let the app verify and only have nginx check that Authorization exists. Pick one. Duplicating verification in nginx and in Node is how you get two parsers of the same token with two bug lists.

nginx
location = /_auth {
    internal;
    proxy_pass http://127.0.0.1:9090/verify;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header Authorization $http_authorization;
}

location /v1/billing/ {
    auth_request /_auth;
    auth_request_set $user_id $upstream_http_x_user_id;
    proxy_set_header X-User-Id $user_id;
    proxy_pass http://billing;
}

The verifier is a local process on the edge node. It does not call a SaaS. It does not open Postgres for every request if you can verify a signed token with a public key on disk. Cache JWKS with a TTL. Failure mode is 401, not 502 with a stack trace from a vendor.

Edge nginx is the gateway Client TLS to edge Edge VPS nginx route, limit, body cap auth_request optional Orders VPS 10.0.0.21 Billing VPS 10.0.0.22 Not proxied Redis / Postgres Lucknow DC01 L3/L4 DDoS at edge

Upstreams Are Nodes, Not a Mesh

Each upstream server line is a VPS. Health is fail_timeout, not a service mesh sidecar. If you need to drain a node, remove it from the upstream and reload. nginx -s reload is the change protocol. Keep the generated config in the control plane so a tenant-to-node map and this gateway stay in sync. Do not hand-edit production server blocks after the third API.

L3/L4 DDoS filtering in front of the edge still leaves application-layer abuse. limit_req is that layer. Tune it from access logs, not from a vendor default of 1 request per second that will lock out a NAT. Return 429 with a Retry-After header your clients already understand.

Do not proxy /redis or /metrics to the world because it was convenient for a laptop. The gateway's job is also to not be a universal reverse proxy. Default deny locations. Only the prefixes you listed exist.

Access logs on the edge are the source of truth for 429s, upstream 5xx, and slow routes. json log format with request_id, upstream_addr, and request_time is enough to decide whether to split a backend node. You do not need a product that wraps nginx to get that.

Takeaway

nginx on an edge VPS is an API gateway when you give it routing, limits, TLS, and a short timeout, and you refuse to let it become an application. Separate nodes behind it keep blast radius and deploys independent. You do not need a managed gateway SKU to get that shape.

Put the edge on its own Netbay VPS in Lucknow (DC01) and keep Redis and Postgres off the public server_name entirely — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance