g3

The whole API gateway is four files.

g3 puts auth, rate limits, request and response rewrites, retries and hot reload in a 9.6 MB container image. It's one static binary built only on the Go standard library, with no shell, no libc and no third-party code.

Open this page on a laptop to download g3

g3 runs with Docker or Podman on a computer or server. Open this page there to read the details and download the image.

$ ls -l g3:1.0.0-alpha.4
/g3the gateway9.40 MB
/etc/ssl/certs/ca-certificates.crtto verify upstream TLS179 KB
/etc/passwdthe non-root user57 B
/etc/groupits group17 B
image total9.6 MB

Built on an empty base image and run as user 65532. There's nothing else to exec into, and almost nothing for a scanner to flag.

What happens to a request

Every request takes the same path through the gateway. Each stage is set in one JSON file, globally, per service or per route, and a route's setting overrides its service's.

  1. 1Clean

    Dot segments, encoded slashes, control bytes and odd methods are refused before routing.

  2. 2Match

    Paths with parameters such as /users/{id}, methods and hosts.

  3. 3Filter

    IP allow and deny lists, and CORS answered at the edge.

  4. 4Limit

    Rate limits per second, minute and hour, plus body size caps.

  5. 5Authenticate

    JWT, OIDC login, token introspection, API keys or mTLS.

  6. 6Rewrite

    Path, headers and query string, using values from the path.

  7. 7Upstream

    Load balanced, circuit broken, and retried only when that's safe.

  8. 8Respond

    Response headers and top-level JSON fields renamed, removed or added.

Everything a gateway needs, nothing it doesn't

No plugins to install and no database to run. Everything below ships in the one binary.

Identity

  • OAuth 2 and OpenID Connect. Works with Keycloak, Auth0, Entra ID, Okta, Google and Dex, with keys from JWKS that rotate without a restart.
  • Browser login. Authorization code flow with PKCE, sessions in encrypted __Host- cookies, automatic token refresh.
  • Opaque tokens. RFC 7662 introspection with a bounded cache keyed by token hash.
  • Per-client API keys. Grouped by consumer, scoped to routes, rotated by config edit. Only hashes are kept in memory.
  • Mutual TLS. From its own handshake or from your load balancer's header, with CRLs, SPIFFE IDs and key pinning.

Traffic

  • Rewrites both ways. Rename, remove or add headers and query parameters going in; headers and JSON fields coming back.
  • Rate limiting. GCRA with burst, per client IP (IPv6 grouped by /64) or global.
  • Load balancing. Power of two choices on in-flight requests, with a circuit breaker per target and optional health checks.
  • Safe retries. Only when a retry can't cause a duplicate, sent to a different target, within a retry budget.
  • Load shedding. Concurrency limits overall and per service, with Retry-After on the way out.

Security

  • Modern TLS. TLS 1.2+ with forward-secret AEAD suites, post-quantum X25519MLKEM768 key exchange preferred, and HTTP/2.
  • Forging blocked. Identity headers are stripped from every inbound request, and forwarding headers are trusted only from your proxies.
  • Brute-force lockout. 20 wrong credentials in a minute locks a client out for a minute.
  • Quiet errors. Minimal JSON with a request ID. Upstream Server headers are stripped.

Operations

  • Hot reload. Config, certificates, keys and CA files are watched. A bad config is rejected and the running one stays.
  • Validate before you deploy. g3 check reports every problem in a config at once, without serving traffic.
  • Observable. Prometheus metrics, health and readiness endpoints, W3C traceparent propagation.
  • Graceful. Drains on SIGTERM, stops stalled clients without cutting off large uploads, and sizes its memory to the container limit.

One JSON file

Unknown fields, missing secrets and conflicting routes are rejected when the config loads, so a typo never reaches traffic.

Secrets stay out of the file
Write ${NAME} and the value comes from the environment. An unset variable fails the load instead of becoming an empty key.
This example
Lets partners with an API key call /v1/users/42/orders, sends it to /internal/orders?user=42, and removes internal_notes from the reply.
{
  "plugins": [
    { "name": "rate-limiting",
      "config": { "second": 20, "minute": 600 } }
  ],
  "consumers": [
    { "name": "acme", "groups": ["partners"],
      "api_keys": ["${ACME_API_KEY}"] }
  ],
  "services": [{
    "name": "orders",
    "url": "http://orders.internal:8080",
    "plugins": [
      { "name": "auth", "config": { "auth": {
          "type": "apikey",
          "consumer_groups": ["partners"] } } }
    ],
    "routes": [{
      "name": "user-orders",
      "paths": ["/v1/users/{id}/orders"],
      "methods": ["GET"],
      "plugins": [
        { "name": "request-transformer", "config": {
            "replace_uri": "/internal/orders",
            "add_query": { "user": "{id}" } } },
        { "name": "response-transformer", "config": {
            "remove_json": ["internal_notes"] } }
      ]
    }]
  }]
}

Run it in a minute

You need Docker or Podman on Linux, macOS or Windows. The image is built for linux/amd64.

  1. Load the image

    Download the file below, then load it. It's tagged g3:1.0.0-alpha.4.

    docker load -i g3-1.0.0-alpha.4-linux-amd64.tar.gz
  2. Write a config

    This is a complete config. It sends every request to a public echo service.

    cat > gateway.json <<'EOF'
    {
      "services": [{
        "name": "echo",
        "url": "https://postman-echo.com",
        "routes": [{ "name": "all", "paths": ["/"] }]
      }]
    }
    EOF
  3. Check it, then run it

    Traffic is served on 8080. Health, readiness and metrics are on 9901; keep that port private.

    docker run --rm -v "$PWD/gateway.json:/etc/gateway/gateway.json:ro" g3:1.0.0-alpha.4 check
    
    docker run --rm --read-only -p 8080:8080 -p 9901:9901 \
      -v "$PWD/gateway.json:/etc/gateway/gateway.json:ro" g3:1.0.0-alpha.4
  4. Send a request

    The echo service replies with what it received, including the headers the gateway added.

    curl "localhost:8080/get?hello=world"

Download g3

The container image as a compressed archive for docker load or podman load.

Version
1.0.0-alpha.4
Platform
linux/amd64
Download
4.0 MB
Image
9.6 MB
Download the image 4.0 MB
Download it from a laptop

The image is for Docker or Podman on Linux, macOS or Windows. Open this page on that computer to download it.

SHA-256 39b56b56d5e181efa60342161b9a9badeb9b3d16cc4daa718fee2a97ceaad1b0