Skip to main content

Unkey vs Zuplo vs Kong Gateway 2026

·PkgPulse Team
0

TL;DR: Unkey is the open-source API key management platform — sub-millisecond key verification, built-in rate limiting, usage analytics, and temporary keys with no gateway to deploy. Zuplo is the programmable API gateway built on Cloudflare Workers — edge-deployed, TypeScript policies, OpenAPI-native, and developer portal included. Kong Gateway is the enterprise API gateway — plugin ecosystem, service mesh, multi-protocol support, and the most mature self-hosted option. In 2026: Unkey for API key management without a full gateway, Zuplo for edge-native programmable gateways, Kong for enterprise API infrastructure.

Key Takeaways

  • Unkey: Open-source (Apache 2.0), key management focused. API key creation/verification, rate limiting, usage tracking, temporary keys. Not a full gateway — integrates into your existing API. Best for adding API key auth and rate limiting without deploying infrastructure
  • Zuplo: Cloud-native, edge-deployed. TypeScript request/response policies, OpenAPI-first, built-in developer portal, Cloudflare Workers runtime. Best for API products needing a gateway with developer portal and edge performance
  • Kong Gateway: Open-source + enterprise. Plugin architecture, service mesh (Kuma), multi-protocol (REST, gRPC, GraphQL, WebSocket), Kubernetes-native. Best for enterprise API infrastructure with complex routing and plugin needs

Unkey — API Key Management

Unkey gives you API key management, rate limiting, and usage tracking without deploying a gateway — just verify keys inline.

Creating and Managing API Keys

import { Unkey } from "@unkey/api";

const unkey = new Unkey({ rootKey: process.env.UNKEY_ROOT_KEY! });

// Create an API key
const { result } = await unkey.keys.create({
  apiId: process.env.UNKEY_API_ID!,
  prefix: "sk_live", // Key prefix for identification
  name: "Acme Corp Production",
  ownerId: "customer_42", // Link to your customer
  meta: {
    plan: "enterprise",
    company: "Acme Corp",
  },
  // Rate limiting
  ratelimit: {
    type: "fast", // "fast" (local) or "consistent" (global)
    limit: 1000,
    refillRate: 100, // 100 tokens per interval
    refillInterval: 1000, // every 1 second
  },
  // Auto-expire after 90 days
  expires: Date.now() + 90 * 24 * 60 * 60 * 1000,
  // Usage limits
  remaining: 1000000, // Max 1M requests total
});

console.log(`Key: ${result.key}`); // sk_live_abc123...
console.log(`Key ID: ${result.keyId}`);

Verifying API Keys

import { verifyKey } from "@unkey/api";

// Verify in your API handler — sub-millisecond
async function authenticateRequest(req: Request): Promise<{
  valid: boolean;
  ownerId?: string;
  meta?: Record<string, unknown>;
  ratelimit?: { remaining: number };
}> {
  const apiKey = req.headers.get("Authorization")?.replace("Bearer ", "");
  if (!apiKey) return { valid: false };

  const { result, error } = await verifyKey({
    key: apiKey,
    apiId: process.env.UNKEY_API_ID!,
  });

  if (error || !result.valid) {
    return { valid: false };
  }

  return {
    valid: true,
    ownerId: result.ownerId,
    meta: result.meta,
    ratelimit: result.ratelimit
      ? { remaining: result.ratelimit.remaining }
      : undefined,
  };
}

// Express middleware
function unkeyAuth(req: Request, res: Response, next: NextFunction) {
  authenticateRequest(req).then(({ valid, ownerId, meta, ratelimit }) => {
    if (!valid) {
      return res.status(401).json({ error: "Invalid API key" });
    }

    if (ratelimit && ratelimit.remaining <= 0) {
      return res.status(429).json({ error: "Rate limit exceeded" });
    }

    req.customerId = ownerId;
    req.plan = meta?.plan;
    next();
  });
}

app.use("/api/*", unkeyAuth);

Rate Limiting

// Standalone rate limiting (without API keys)
import { Ratelimit } from "@unkey/ratelimit";

const limiter = new Ratelimit({
  rootKey: process.env.UNKEY_ROOT_KEY!,
  namespace: "api.requests",
  limit: 100,
  duration: "60s", // 100 requests per 60 seconds
});

app.use("/api/*", async (req, res, next) => {
  const identifier = req.ip || req.headers["x-forwarded-for"];
  const { success, remaining, reset } = await limiter.limit(identifier);

  res.setHeader("X-RateLimit-Remaining", remaining);
  res.setHeader("X-RateLimit-Reset", reset);

  if (!success) {
    return res.status(429).json({
      error: "Rate limit exceeded",
      retryAfter: Math.ceil((reset - Date.now()) / 1000),
    });
  }

  next();
});

// Tiered rate limiting based on plan
async function tierLimiter(req: Request, res: Response, next: NextFunction) {
  const plan = req.plan || "free";
  const limits = {
    free: { limit: 100, duration: "60s" },
    pro: { limit: 1000, duration: "60s" },
    enterprise: { limit: 10000, duration: "60s" },
  };

  const config = limits[plan];
  const ratelimit = new Ratelimit({
    rootKey: process.env.UNKEY_ROOT_KEY!,
    namespace: `api.${plan}`,
    ...config,
  });

  const { success, remaining } = await ratelimit.limit(req.customerId);
  if (!success) return res.status(429).json({ error: "Rate limit exceeded" });

  res.setHeader("X-RateLimit-Remaining", remaining);
  next();
}

Key Analytics and Management

// List keys for a customer
const { result: keys } = await unkey.keys.list({
  apiId: process.env.UNKEY_API_ID!,
  ownerId: "customer_42",
});

for (const key of keys.keys) {
  console.log(`${key.name}: ${key.start}... (${key.remaining} remaining)`);
}

// Update a key
await unkey.keys.update({
  keyId: keyId,
  ratelimit: {
    type: "fast",
    limit: 5000, // Upgrade rate limit
    refillRate: 500,
    refillInterval: 1000,
  },
  meta: { plan: "enterprise-plus" },
});

// Revoke a key
await unkey.keys.delete({ keyId: keyId });

// Get usage analytics
const { result: analytics } = await unkey.keys.getVerifications({
  keyId: keyId,
  start: Date.now() - 7 * 24 * 60 * 60 * 1000, // Last 7 days
  granularity: "day",
});

for (const day of analytics.verifications) {
  console.log(`${day.time}: ${day.success} ok, ${day.rateLimited} limited`);
}

Zuplo — Edge-Native Programmable Gateway

Zuplo is a programmable API gateway deployed to 300+ edge locations — TypeScript policies, OpenAPI-first design, and a built-in developer portal.

Gateway Configuration

// routes.oas.json — OpenAPI-based route configuration
{
  "openapi": "3.1.0",
  "info": { "title": "Acme API", "version": "2.0" },
  "paths": {
    "/v2/projects": {
      "get": {
        "operationId": "listProjects",
        "x-zuplo-route": {
          "handler": {
            "module": "$import(@zuplo/runtime)",
            "export": "urlForwardHandler",
            "options": {
              "baseUrl": "https://api-internal.acme.com"
            }
          },
          "policies": {
            "inbound": [
              "api-key-auth",
              "rate-limit-inbound",
              "request-validation"
            ],
            "outbound": [
              "remove-internal-headers"
            ]
          }
        }
      }
    }
  }
}

Custom TypeScript Policies

// modules/policies/custom-auth.ts
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";

export default async function customAuth(
  request: ZuploRequest,
  context: ZuploContext,
  options: { requiredScopes?: string[] },
  policyName: string
) {
  const apiKey = request.headers.get("authorization")?.replace("Bearer ", "");

  if (!apiKey) {
    return new Response(JSON.stringify({ error: "Missing API key" }), {
      status: 401,
      headers: { "Content-Type": "application/json" },
    });
  }

  // Verify key against your auth system
  const keyInfo = await context.cache.get(`key:${apiKey}`);

  if (!keyInfo) {
    // Cache miss — verify against backend
    const verification = await fetch("https://auth.acme.com/verify", {
      method: "POST",
      body: JSON.stringify({ key: apiKey }),
    });

    if (!verification.ok) {
      return new Response(JSON.stringify({ error: "Invalid API key" }), {
        status: 401,
      });
    }

    const data = await verification.json();
    await context.cache.set(`key:${apiKey}`, JSON.stringify(data), 300); // 5 min cache
  }

  // Check scopes
  if (options.requiredScopes) {
    const scopes = keyInfo.scopes || [];
    const hasScope = options.requiredScopes.every((s) => scopes.includes(s));
    if (!hasScope) {
      return new Response(JSON.stringify({ error: "Insufficient scope" }), {
        status: 403,
      });
    }
  }

  // Attach user info to request for downstream handlers
  request.user = keyInfo;
  return request; // Continue to next policy/handler
}

Request/Response Transformation

// modules/policies/transform-response.ts
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";

export default async function transformResponse(
  response: Response,
  request: ZuploRequest,
  context: ZuploContext,
  options: {},
  policyName: string
) {
  const body = await response.json();

  // Transform the response
  const transformed = {
    data: body.results,
    pagination: {
      total: body.total_count,
      page: body.page,
      perPage: body.per_page,
      nextCursor: body.next_cursor,
    },
    meta: {
      requestId: context.requestId,
      timestamp: new Date().toISOString(),
    },
  };

  return new Response(JSON.stringify(transformed), {
    status: response.status,
    headers: {
      "Content-Type": "application/json",
      "X-Request-Id": context.requestId,
      "Cache-Control": "public, max-age=60",
    },
  });
}

Built-in Developer Portal

// zuplo.jsonc — developer portal configuration
{
  "developerPortal": {
    "enabled": true,
    "pageTitle": "Acme API Documentation",
    "faviconUrl": "/public/favicon.ico",
    "logoUrl": "/public/logo.svg",
    "theme": {
      "primary": "#0D9373",
      "background": "#0a0a0a"
    },
    "authentication": {
      "provider": "auth0",
      "issuer": "https://acme.auth0.com/",
      "clientId": "abc123"
    },
    "generateExamples": true,
    "enableKeyManagement": true
  }
}

Kong Gateway — Enterprise API Infrastructure

Kong Gateway is the enterprise-grade API gateway — plugin ecosystem, service mesh integration, and multi-protocol support.

Kubernetes Ingress Configuration

# Kong Ingress Controller — Kubernetes-native
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rate-limiting
config:
  minute: 100
  policy: redis
  redis:
    host: redis.default.svc.cluster.local
    port: 6379
plugin: rate-limiting

---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: key-auth
plugin: key-auth

---
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: cors
config:
  origins: ["https://app.acme.com"]
  methods: ["GET", "POST", "PUT", "DELETE"]
  headers: ["Authorization", "Content-Type"]
  max_age: 3600
plugin: cors

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-gateway
  annotations:
    konghq.com/plugins: rate-limiting, key-auth, cors
    konghq.com/strip-path: "true"
spec:
  ingressClassName: kong
  rules:
    - host: api.acme.com
      http:
        paths:
          - path: /v2/projects
            pathType: Prefix
            backend:
              service:
                name: project-service
                port:
                  number: 8080
          - path: /v2/users
            pathType: Prefix
            backend:
              service:
                name: user-service
                port:
                  number: 8080

Admin API

// Kong Admin API — manage configuration
const KONG_ADMIN = "http://kong-admin:8001";

// Create a service
await fetch(`${KONG_ADMIN}/services`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "project-service",
    url: "http://project-svc.default.svc.cluster.local:8080",
    retries: 3,
    connect_timeout: 5000,
    read_timeout: 30000,
  }),
});

// Create a route
await fetch(`${KONG_ADMIN}/services/project-service/routes`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "projects-route",
    paths: ["/v2/projects"],
    methods: ["GET", "POST", "PUT", "DELETE"],
    strip_path: true,
    protocols: ["https"],
  }),
});

// Enable plugins on a service
await fetch(`${KONG_ADMIN}/services/project-service/plugins`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "rate-limiting",
    config: {
      minute: 1000,
      hour: 50000,
      policy: "redis",
      redis: { host: "redis", port: 6379 },
    },
  }),
});

// JWT authentication plugin
await fetch(`${KONG_ADMIN}/services/project-service/plugins`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "jwt",
    config: {
      claims_to_verify: ["exp"],
      key_claim_name: "iss",
      header_names: ["Authorization"],
    },
  }),
});

// Request transformation
await fetch(`${KONG_ADMIN}/services/project-service/plugins`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    name: "request-transformer",
    config: {
      add: {
        headers: ["X-Request-ID:$(uuid)"],
        querystring: ["version:v2"],
      },
      remove: {
        headers: ["X-Internal-Token"],
      },
    },
  }),
});

Custom Plugin (Lua)

-- kong/plugins/custom-auth/handler.lua
local CustomAuth = {
  PRIORITY = 1000,
  VERSION = "1.0.0",
}

function CustomAuth:access(conf)
  local api_key = kong.request.get_header("X-API-Key")

  if not api_key then
    return kong.response.exit(401, { message = "Missing API key" })
  end

  -- Verify against external service
  local httpc = require("resty.http").new()
  local res, err = httpc:request_uri(conf.auth_url, {
    method = "POST",
    body = kong.table.new(0, 1),
    headers = {
      ["Content-Type"] = "application/json",
    },
  })

  if not res or res.status ~= 200 then
    return kong.response.exit(403, { message = "Invalid API key" })
  end

  -- Set consumer headers for upstream
  local body = require("cjson").decode(res.body)
  kong.service.request.set_header("X-Consumer-ID", body.customer_id)
  kong.service.request.set_header("X-Consumer-Plan", body.plan)
end

return CustomAuth

Feature Comparison

FeatureUnkeyZuploKong Gateway
TypeAPI key managementProgrammable gatewayFull API gateway
DeploymentCloud (no infra)Edge (300+ PoPs)Self-hosted or cloud
LicenseApache 2.0ProprietaryApache 2.0 + Enterprise
API Key Management✅ (core feature)✅ (built-in)Plugin (key-auth)
Rate Limiting✅ (global + local)✅ (edge-native)Plugin (Redis-backed)
Request Routing❌ (not a gateway)
Request Transformation✅ (TypeScript)✅ (plugins)
AuthenticationAPI keysAPI keys, JWT, OAuthAPI keys, JWT, OAuth, OIDC, LDAP
Developer Portal✅ (built-in)Kong Portal (Enterprise)
Custom LogicN/ATypeScript policiesLua plugins
OpenAPI Support✅ (OpenAPI-first)Spec-based routes
gRPC Support
WebSocket Support
Service Mesh✅ (Kuma)
Analytics✅ (key usage)✅ (request analytics)✅ (Vitals - Enterprise)
Kubernetes Native✅ (Ingress Controller)
Plugin EcosystemN/APolicies (TypeScript)100+ plugins
Latency Overhead<1ms (key verify)<5ms (edge)1-10ms
ComplexityVery lowLowMedium-High
Best ForAPI key auth/limitsEdge API gatewayEnterprise infrastructure

When to Use Each

Choose Unkey if:

  • You need API key management without deploying a gateway
  • Sub-millisecond key verification with built-in rate limiting is important
  • Temporary keys with auto-expiry and usage caps fit your use case
  • You already have an API and just need auth + rate limiting added
  • Per-key analytics and usage tracking drive billing or monitoring

Choose Zuplo if:

  • You're building an API product and need a gateway with developer portal
  • Edge deployment (300+ locations) for low-latency global access matters
  • TypeScript-based request/response policies give your team flexibility
  • OpenAPI-first design with automatic validation is important
  • You want a modern gateway that deploys like a Cloudflare Worker

Choose Kong Gateway if:

  • Enterprise API infrastructure with 100+ plugins is needed
  • Multi-protocol support (REST, gRPC, GraphQL, WebSocket) is important
  • Kubernetes Ingress Controller for service mesh integration matters
  • Self-hosted deployment for compliance and data residency is required
  • You need service mesh capabilities (Kuma) alongside API gateway

Ecosystem and Community Health

Unkey is open-source (Apache 2.0) and has built a strong following among API-first startups and developer tool companies. Founded by Andreas Thomas and now backed by funding from several investor groups, Unkey is developing rapidly. The GitHub repository serves both as the source code for the cloud service and as a deployable self-hosted option, which gives developers full transparency. The TypeScript SDK is the primary integration path, and the quality and documentation of that SDK are consistently praised in the developer community.

Zuplo's position changed significantly when Cloudflare made it a preferred gateway partner for Workers deployments. Zuplo runs natively on Cloudflare's infrastructure, meaning the gateway has the same global footprint (300+ edge locations) as Cloudflare Workers without any additional configuration. This tight integration makes Zuplo the natural choice for API companies already deployed on Cloudflare. The built-in developer portal — which auto-generates from your OpenAPI spec and handles key management — removes the need for a separate developer portal product.

Kong Gateway has the longest history and the deepest enterprise adoption. Banks, telecoms, and large government deployments run Kong to handle billions of API calls per day. The plugin ecosystem — over 100 official plugins and a large marketplace of community plugins — means almost any API management requirement can be addressed without custom code. Kong's Kubernetes Ingress Controller (KIC) is particularly popular for teams that have moved to Kubernetes and want API gateway behavior to live alongside their service definitions.

API Gateway and the Broader API Infrastructure Stack

API gateways exist within a broader infrastructure context. For Node.js applications, the gateway sits in front of the application servers and handles cross-cutting concerns — rate limiting, authentication validation, request logging, response caching — so that the application code doesn't need to. The application server (whether running Hono, Express, Fastify, or NestJS) focuses on business logic while the gateway handles infrastructure concerns.

The choice of API gateway often follows the choice of deployment infrastructure. Teams deploying to Cloudflare Workers are natural Zuplo users. Teams running Kubernetes deployments at scale tend toward Kong or AWS API Gateway. Teams building SaaS products that need to issue and manage API keys for their customers are natural Unkey users. The "right" gateway is the one that aligns with your infrastructure and team's operational expertise.

For teams building the API layer that sits behind these gateways, the Hono vs Elysia 2026 comparison covers the TypeScript-native HTTP framework options. For authentication middleware that integrates with gateway-level JWT validation, WorkOS vs Stytch vs FusionAuth covers the identity platform options that pair with API gateway authentication plugins.

Rate limiting and API key management are just two dimensions of the API platform problem. Observability — understanding which endpoints are called, by whom, at what rate, and with what error rates — is the third. All three gateways (Unkey, Zuplo, Kong) provide analytics dashboards, but the depth and real-time nature of that analytics differs significantly. Unkey's analytics are key-centric (per-key usage, per-key rate limit status); Zuplo's analytics integrate with Cloudflare's analytics platform for edge-level visibility; Kong's analytics scale to billions of events with plugin integrations for DataDog, Prometheus, and ElasticSearch. Choosing a gateway also means choosing an observability approach, which is worth evaluating alongside the gateway's core rate limiting and routing capabilities. Teams that already have a preferred observability platform should verify that their chosen gateway integrates with it before committing.


Real-World Adoption

Unkey's value proposition resonates most strongly with SaaS companies launching an API product for the first time. When you need to give customers API keys, track usage per key, enforce rate limits by tier, and rotate keys without downtime — Unkey handles all of this in a few hours of integration rather than weeks of custom infrastructure. Companies like OpenAI have popularized the sk_live prefix model for API keys, and Unkey lets you implement exactly that pattern with full observability.

Zuplo is popular with API-first companies building developer platforms: fintech APIs, payment gateways, and data APIs that expose their service through a documented HTTP API with a developer portal. The combination of edge performance, TypeScript-native policy code, and the built-in developer portal makes Zuplo particularly strong for teams that want to iterate on API behavior without infrastructure changes.

Kong's adoption spans industries but is especially deep in financial services and healthcare. The compliance requirements in these industries — audit logging, request/response inspection, mutual TLS, custom authentication protocols — are areas where Kong's extensibility and enterprise support contracts provide genuine risk reduction. Kong Mesh (built on Kuma) extends this to service-to-service communication within Kubernetes clusters, giving platform teams a single tool for both north-south traffic (internet to cluster) and east-west traffic (service to service).


Developer Experience Deep Dive

Unkey's developer experience is intentionally minimal. The dashboard is clean, key creation via the API takes a single HTTP request, and the TypeScript SDK is well-typed with full IntelliSense support. The verifyKey function returns consistent structured data — valid boolean, remaining quota, rate limit info — that's easy to build middleware around. Documentation covers every SDK function, and the interactive playground on the website lets you test key creation before writing code.

The operational simplicity of Unkey deserves emphasis. You add two environment variables, three lines of middleware code, and you have API key authentication with rate limiting and per-key analytics. There's no gateway to deploy, no configuration files, no infrastructure to manage. For a small team that wants to ship an API product, this is genuinely transformative.

Zuplo's developer experience centers on the routes.oas.json file and the policy system. If your team knows OpenAPI, the configuration model will feel natural. The TypeScript policy API is clean — your policy function receives the request, has access to a cache, can make fetch calls, and returns either the modified request or an error response. Local development works via Zuplo's own CLI, which runs a local gateway instance that matches production behavior closely.

Kong's configuration surface area is large, which is both its strength and its friction. The Admin API is comprehensive but requires understanding Kong's data model: services, routes, consumers, plugins. The KIC (Kubernetes Ingress Controller) hides some of this complexity behind Kubernetes annotations, which is the recommended path for new Kong deployments in 2026.


Performance Analysis

Unkey's key verification latency is remarkable. The global distribution of verification nodes means that even without caching in your application, most key verifications complete in under 10ms from anywhere in the world. The "fast" rate limit type uses a local token bucket that makes rate limiting decisions in under 1ms without a network call, at the cost of some accuracy across multiple instances. The "consistent" rate limit uses a distributed counter that's accurate globally but adds 10-20ms per request.

Zuplo's edge deployment on Cloudflare eliminates the round-trip penalty that server-based gateways introduce. When your users are distributed globally and your gateway runs at the edge closest to them, the added gateway latency is typically under 5ms. For APIs where every millisecond matters — financial data APIs, gaming APIs, real-time services — edge deployment is not a nice-to-have but a requirement.

Kong Gateway, running self-hosted, typically adds 1-10ms of latency depending on the number of plugins active. Each plugin in the request pipeline adds processing overhead. Benchmark testing on Kong's own hardware has shown sub-1ms overhead with minimal plugins, scaling to 10ms+ with a full plugin stack including logging, authentication, rate limiting, and request transformation. For most enterprise use cases, this is acceptable.


Migration and Getting Started

For Unkey, the fastest path is: create an account at unkey.com, create an API and note the API ID, generate a root key, install @unkey/api, and add the middleware snippet from the documentation. The whole process takes under an hour for a working integration. If you already have API key management and want to migrate, Unkey's import API lets you bulk-import existing key hashes (it stores hashed keys, not plaintext).

For Zuplo, start with the Zuplo CLI: npm install -g zuplo, create a new project, configure your first route in routes.oas.json pointing to a backend service, add the built-in api-key-auth policy to the route, and deploy. The Zuplo dashboard then handles the developer portal automatically from your OpenAPI spec.

For Kong, the recommended starting point in 2026 is the Kubernetes Ingress Controller. Add Kong to your cluster via Helm, convert your existing Ingress resources to use the Kong ingress class, and start adding KongPlugin annotations to your Ingress definitions. This incremental approach lets you adopt Kong gradually without a big-bang migration.


Final Verdict 2026

Choose Unkey when you're adding API key management to an existing API without wanting to deploy gateway infrastructure. If you're a SaaS company that needs to expose a customer-facing API with per-customer rate limits, key rotation, and usage analytics, Unkey is the fastest and most focused solution.

Choose Zuplo when you're building an API product from scratch and want the developer portal, edge deployment, and TypeScript policy system in one package. For developer-facing APIs where documentation and key management are part of the product experience, Zuplo is the most complete modern option.

Choose Kong Gateway when you're operating enterprise-scale API infrastructure with Kubernetes, complex multi-protocol requirements, or compliance needs that require a self-hosted, auditable, extensively plugin-extended gateway.


Methodology

Feature comparison based on Unkey, Zuplo, and Kong Gateway (OSS + Enterprise) documentation as of March 2026. Unkey evaluated on key management API, rate limiting, and verification latency. Zuplo evaluated on edge performance, policy system, and developer portal. Kong evaluated on plugin ecosystem, protocol support, and Kubernetes integration. Code examples use official SDKs and REST APIs.


Related:

Best Node.js Background Job Libraries 2026

Hono vs Elysia 2026

Best WebSocket Libraries for Node.js 2026

The 2026 JavaScript Stack Cheatsheet

One PDF: the best package for every category (ORMs, bundlers, auth, testing, state management). Used by 500+ devs. Free, updated monthly.