zuplo 7.3.2 → 7.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/docs/ai-gateway/apps.mdx +2 -2
  2. package/docs/ai-gateway/custom-policies.mdx +3 -3
  3. package/docs/ai-gateway/fallback.mdx +13 -12
  4. package/docs/ai-gateway/getting-started.mdx +10 -9
  5. package/docs/ai-gateway/introduction.mdx +19 -18
  6. package/docs/ai-gateway/managing-apps.mdx +9 -7
  7. package/docs/ai-gateway/policy-chains.mdx +13 -7
  8. package/docs/ai-gateway/policy-templates.mdx +4 -3
  9. package/docs/ai-gateway/usage-limits.mdx +8 -10
  10. package/docs/api-management/introduction.md +1 -1
  11. package/docs/articles/api-key-api.mdx +3 -3
  12. package/docs/articles/custom-ci-cd-azure.mdx +1 -1
  13. package/docs/articles/custom-ci-cd-bitbucket.mdx +2 -2
  14. package/docs/articles/custom-code-patterns.md +1 -1
  15. package/docs/articles/custom-domains.mdx +2 -2
  16. package/docs/articles/development-options.mdx +4 -4
  17. package/docs/articles/fastly-zuplo-host-setup.mdx +5 -5
  18. package/docs/articles/feature-flags.mdx +442 -0
  19. package/docs/articles/gke-with-upstream-auth-policy.mdx +7 -7
  20. package/docs/articles/health-checks.mdx +4 -4
  21. package/docs/articles/hosting-options.mdx +2 -2
  22. package/docs/articles/local-development-env-variables.mdx +1 -1
  23. package/docs/articles/metrics-plugins.mdx +1 -1
  24. package/docs/articles/migration-overview.md +1 -1
  25. package/docs/articles/monorepo-deployment.mdx +10 -10
  26. package/docs/articles/performance-testing.mdx +10 -9
  27. package/docs/articles/plugin-azure-blob.mdx +1 -1
  28. package/docs/articles/plugin-azure-event-hubs.mdx +2 -2
  29. package/docs/articles/policies.mdx +2 -2
  30. package/docs/articles/securing-backend-mtls.mdx +3 -3
  31. package/docs/articles/securing-the-gateway-with-client-mtls.mdx +3 -3
  32. package/docs/articles/securing-your-backend.mdx +1 -1
  33. package/docs/articles/security.mdx +1 -1
  34. package/docs/articles/terraform.mdx +2 -2
  35. package/docs/articles/testing.mdx +6 -6
  36. package/docs/articles/troubleshooting-slow-responses.mdx +5 -6
  37. package/docs/articles/troubleshooting.md +1 -1
  38. package/docs/articles/use-openapi-extension-data.mdx +4 -4
  39. package/docs/articles/waf-ddos-akamai.md +13 -13
  40. package/docs/articles/waf-ddos-aws-waf-shield.mdx +14 -14
  41. package/docs/articles/waf-ddos-fastly.mdx +14 -14
  42. package/docs/articles/waf-ddos.mdx +7 -7
  43. package/docs/cli/authentication.mdx +1 -1
  44. package/docs/cli/lint.mdx +103 -0
  45. package/docs/concepts/how-zuplo-works.mdx +5 -4
  46. package/docs/concepts/upstream-credentials.mdx +1 -1
  47. package/docs/dedicated/akamai/architecture.mdx +23 -24
  48. package/docs/dedicated/akamai/cdn.mdx +20 -20
  49. package/docs/dedicated/architecture.mdx +28 -27
  50. package/docs/dedicated/custom-domains.mdx +3 -4
  51. package/docs/dedicated/federated-gateways.mdx +1 -1
  52. package/docs/dedicated/networking.mdx +10 -10
  53. package/docs/dedicated/overview.mdx +3 -3
  54. package/docs/dedicated/source-control.mdx +6 -5
  55. package/docs/handlers/custom-handler.mdx +4 -4
  56. package/docs/handlers/mcp-server.mdx +1 -1
  57. package/docs/handlers/url-forward.mdx +1 -2
  58. package/docs/mcp-server/introduction.mdx +4 -4
  59. package/docs/policies/_index.md +2 -2
  60. package/docs/policies/ai-gateway-configuration-executor-v2-inbound/schema.json +1 -1
  61. package/docs/policies/ai-gateway-dlp-inbound/doc.md +79 -45
  62. package/docs/policies/ai-gateway-dlp-inbound/schema.json +5679 -3359
  63. package/docs/policies/ai-gateway-metering-v2-inbound/doc.md +13 -13
  64. package/docs/policies/ai-gateway-metering-v2-inbound/schema.json +1 -1
  65. package/docs/programmable-api/environment.mdx +1 -1
  66. package/docs/programmable-api/jwt-service-plugin.mdx +1 -1
  67. package/docs/programmable-api/logger.mdx +1 -1
  68. package/docs/programmable-api/runtime-errors.mdx +1 -1
  69. package/docs/programmable-api/zuplo-context.mdx +3 -3
  70. package/docs/self-hosted/overview.md +3 -3
  71. package/package.json +5 -5
@@ -0,0 +1,442 @@
1
+ ---
2
+ title: Use Feature Flags to Gate Your API
3
+ sidebar_label: Feature Flags & Gating
4
+ description:
5
+ Evaluate feature flags from providers like Statsig, PostHog, Flagsmith, and
6
+ GrowthBook inside Zuplo policies. Cache per-user evaluations for low latency
7
+ and load global flags in the background so they never block a request.
8
+ tags:
9
+ - integrations
10
+ - custom-code
11
+ - caching
12
+ ---
13
+
14
+ Zuplo doesn't have a dedicated feature-flag policy — instead, every provider
15
+ works, because you evaluate flags in custom code. This guide shows the patterns
16
+ that keep flag checks fast on a gateway, with worked examples for Statsig,
17
+ PostHog, Flagsmith, and GrowthBook:
18
+
19
+ - **Live evaluation with caching** — call the provider's API on the request and
20
+ cache the result per user for a short TTL. Use for flags targeted at
21
+ individual users, plans, or tenants.
22
+ - **Background loading** — load flags that apply globally (kill switches,
23
+ maintenance mode, flag definitions) with the
24
+ [BackgroundLoader](../programmable-api/background-loader.mdx), which refreshes
25
+ out of band instead of blocking requests.
26
+ - **Provider SDK with local evaluation** — evaluate flags in-process with no
27
+ per-request provider call, at the cost of a heavier cold start. See
28
+ [Statsig, fully local](#statsig-fully-local).
29
+
30
+ ## Choose a pattern
31
+
32
+ | Pattern | Best for | Latency cost per request |
33
+ | ---------------------------------- | -------------------------------------------------- | --------------------------------------------------- |
34
+ | Live evaluation + cache | Per-user or per-plan targeting | One provider call per user per TTL window |
35
+ | Background loading | Global flags, kill switches, flag definition files | None in the steady state; refreshes run out of band |
36
+ | Provider SDK with local evaluation | Complex targeting rules, many gates per request | None after initialization, but heavier cold start |
37
+
38
+ Most APIs mix these: a background-loaded global flag set plus a small number of
39
+ cached per-user checks on the routes that need them.
40
+
41
+ ## Prerequisites
42
+
43
+ - A Zuplo project with an authentication policy on the routes you want to gate
44
+ (for example [API key authentication](../policies/api-key-inbound.mdx)). The
45
+ examples read `request.user`, which an inbound authentication policy populates
46
+ — `request.user.sub` is the user identifier and `request.user.data` carries
47
+ JWT claims or API key metadata such as the customer's `plan`. See
48
+ [Request User](../programmable-api/request-user.mdx).
49
+ - An API key or token from your flag provider, stored as a secret
50
+ [environment variable](./environment-variables.mdx). Where to find each one:
51
+
52
+ | Variable | Provider | Where to find it | Secret? |
53
+ | --------------------------- | ---------- | -------------------------------------------------- | ------- |
54
+ | `STATSIG_SERVER_KEY` | Statsig | Console → Settings → API Keys → Server Secret Key | Yes |
55
+ | `STATSIG_CLIENT_KEY` | Statsig | Console → Settings → API Keys → Client SDK Key | No |
56
+ | `POSTHOG_PROJECT_TOKEN` | PostHog | Project Settings → Project ID → project token | No |
57
+ | `FLAGSMITH_ENVIRONMENT_KEY` | Flagsmith | Environment settings → client-side environment key | No |
58
+ | `GROWTHBOOK_CLIENT_KEY` | GrowthBook | SDK Connections → client key | No |
59
+
60
+ New environment variables require a redeployment before your code sees them.
61
+
62
+ You only need the variables for the providers you use — skip the rest.
63
+
64
+ ## Pattern 1: Live evaluation with caching
65
+
66
+ Every major provider exposes an HTTP endpoint that evaluates a flag for a user
67
+ and returns the result. Call it on the first request, then cache the result in a
68
+ [MemoryZoneReadThroughCache](../programmable-api/memory-zone-read-through-cache.mdx)
69
+ so subsequent requests for the same user skip the network call.
70
+
71
+ This example checks a Statsig gate and caches the result for 60 seconds:
72
+
73
+ ```ts title="modules/feature-gate-policy.ts"
74
+ import {
75
+ HttpProblems,
76
+ MemoryZoneReadThroughCache,
77
+ ZuploContext,
78
+ ZuploRequest,
79
+ environment,
80
+ } from "@zuplo/runtime";
81
+
82
+ const CACHE_NAME = "feature-flags";
83
+ const CACHE_TTL_SECONDS = 60;
84
+
85
+ async function isGateEnabled(
86
+ gateName: string,
87
+ userId: string,
88
+ context: ZuploContext,
89
+ ): Promise<boolean> {
90
+ const cache = new MemoryZoneReadThroughCache<boolean>(CACHE_NAME, context);
91
+ const cacheKey = `statsig:${gateName}:${userId}`;
92
+
93
+ const cached = await cache.get(cacheKey);
94
+ if (cached !== undefined) {
95
+ return cached;
96
+ }
97
+
98
+ const response = await fetch("https://api.statsig.com/v1/check_gate", {
99
+ method: "POST",
100
+ headers: {
101
+ "Content-Type": "application/json",
102
+ "statsig-api-key": environment.STATSIG_SERVER_KEY,
103
+ },
104
+ body: JSON.stringify({
105
+ gateName,
106
+ user: { userID: userId },
107
+ }),
108
+ });
109
+
110
+ if (!response.ok) {
111
+ // Fail closed: if Statsig is unreachable, deny the feature rather
112
+ // than exposing something that isn't rolled out. Choose deliberately —
113
+ // see "Decide how to fail" below.
114
+ context.log.error(`Statsig check failed: ${response.status}`);
115
+ return false;
116
+ }
117
+
118
+ const result = await response.json();
119
+ const enabled = result.value === true;
120
+ cache.put(cacheKey, enabled, CACHE_TTL_SECONDS);
121
+ return enabled;
122
+ }
123
+
124
+ export default async function policy(
125
+ request: ZuploRequest,
126
+ context: ZuploContext,
127
+ ) {
128
+ const userId = request.user?.sub;
129
+ if (!userId) {
130
+ return HttpProblems.unauthorized(request, context);
131
+ }
132
+
133
+ const enabled = await isGateEnabled("new-beta-endpoint", userId, context);
134
+ if (!enabled) {
135
+ return HttpProblems.forbidden(request, context, {
136
+ detail: "This feature is not enabled for your account",
137
+ });
138
+ }
139
+
140
+ return request;
141
+ }
142
+ ```
143
+
144
+ Only the first request for each user pays for the Statsig call; every request
145
+ after that reads from memory until the TTL expires. Keep the TTL short (30–120
146
+ seconds) so flag changes in the provider propagate quickly. To check several
147
+ gates, fire the `check_gate` calls in parallel with `Promise.all` and cache each
148
+ result under its own key.
149
+
150
+ ### Wire up the policy
151
+
152
+ Register the module as a custom code policy in `config/policies.json`:
153
+
154
+ ```json title="config/policies.json"
155
+ {
156
+ "name": "feature-gate",
157
+ "policyType": "custom-code-inbound",
158
+ "handler": {
159
+ "export": "default",
160
+ "module": "$import(./modules/feature-gate-policy)"
161
+ }
162
+ }
163
+ ```
164
+
165
+ Then add it to the inbound policy chain of each route you want to gate, after
166
+ authentication:
167
+
168
+ ```json title="config/routes.oas.json"
169
+ {
170
+ "paths": {
171
+ "/beta/insights": {
172
+ "get": {
173
+ "x-zuplo-route": {
174
+ "policies": {
175
+ "inbound": ["api-key-auth", "feature-gate"]
176
+ }
177
+ }
178
+ }
179
+ }
180
+ }
181
+ }
182
+ ```
183
+
184
+ ### Verify the gate
185
+
186
+ Call the route twice — once with the flag off and once on:
187
+
188
+ - **Flag off** — the request returns `403` with an `application/problem+json`
189
+ body: `"detail": "This feature is not enabled for your account"`.
190
+ - **Flag on** — the request passes through to the handler normally.
191
+
192
+ Because the example fails closed, a bad key or unreachable Statsig returns the
193
+ same 403 as a disabled flag. Watch the logs for the `Statsig check failed:`
194
+ error line to tell a provider outage apart from a legitimately denied request.
195
+
196
+ ## Pattern 2: Background loading for global flags
197
+
198
+ Some flags apply to everyone: kill switches, maintenance mode, or a global
199
+ rollout. Others are cheapest to fetch as one shared definition file rather than
200
+ per-user evaluations. Either way, there's no reason to make a request wait on
201
+ that fetch — load it in the background instead.
202
+
203
+ The [BackgroundLoader](../programmable-api/background-loader.mdx) returns cached
204
+ data immediately when available, refreshes it asynchronously when the TTL
205
+ expires, and only blocks while the cache is empty on a cold start. Create it at
206
+ module level so the loader is shared across requests handled by the same worker
207
+ process ([isolate](../concepts/how-zuplo-works.mdx)).
208
+
209
+ GrowthBook is a natural fit here: its CDN returns the full feature definition
210
+ payload as a single cacheable JSON document.
211
+
212
+ ```ts title="modules/global-flags-policy.ts"
213
+ import {
214
+ BackgroundLoader,
215
+ HttpProblems,
216
+ ZuploContext,
217
+ ZuploRequest,
218
+ environment,
219
+ } from "@zuplo/runtime";
220
+
221
+ interface GrowthBookFeatures {
222
+ [flagName: string]: { defaultValue: unknown };
223
+ }
224
+
225
+ const featureLoader = new BackgroundLoader<GrowthBookFeatures>(
226
+ async () => {
227
+ const response = await fetch(
228
+ `https://cdn.growthbook.io/api/features/${environment.GROWTHBOOK_CLIENT_KEY}`,
229
+ );
230
+ if (!response.ok) {
231
+ throw new Error(`Failed to load features: ${response.status}`);
232
+ }
233
+ const data = await response.json();
234
+ return data.features;
235
+ },
236
+ {
237
+ ttlSeconds: 60,
238
+ loaderTimeoutSeconds: 5,
239
+ },
240
+ );
241
+
242
+ export default async function policy(
243
+ request: ZuploRequest,
244
+ context: ZuploContext,
245
+ ) {
246
+ // Returns cached definitions immediately in the steady state;
247
+ // the only blocking case is an empty cache on a cold start.
248
+ const features = await featureLoader.get("features");
249
+
250
+ if (features["api-maintenance-mode"]?.defaultValue === true) {
251
+ return HttpProblems.serviceUnavailable(request, context, {
252
+ detail: "This API is temporarily unavailable for maintenance",
253
+ });
254
+ }
255
+
256
+ return request;
257
+ }
258
+ ```
259
+
260
+ Register this module as a `custom-code-inbound` policy in `config/policies.json`
261
+ and add it to the routes you want to gate, exactly as in pattern 1.
262
+
263
+ The same pattern works for any provider payload that isn't user-specific — for
264
+ example a Statsig gate evaluated against a fixed global user, or the Flagsmith
265
+ environment document. One BackgroundLoader per provider keeps each payload on
266
+ its own refresh cadence.
267
+
268
+ :::note
269
+
270
+ The `defaultValue` shortcut covers simple on/off flags. Flags with targeting
271
+ rules or percentage rollouts need an evaluator — either evaluate remotely
272
+ (pattern 1) or pass the definitions to the provider's JavaScript SDK.
273
+
274
+ :::
275
+
276
+ ## More providers
277
+
278
+ The live-evaluation pattern is the same everywhere; only the endpoint, headers,
279
+ and response shape change. Swap the fetch call inside the cached helper — and,
280
+ for providers like PostHog that evaluate all flags in one call, cache the whole
281
+ map keyed by user instead of a boolean keyed by gate and user.
282
+
283
+ ### PostHog
284
+
285
+ PostHog evaluates **all** flags for a user in one call, so cache the whole map
286
+ per `distinct_id`. Use your project token — it's safe for this public endpoint,
287
+ though you should still store it in an environment variable.
288
+
289
+ ```ts
290
+ const response = await fetch("https://us.i.posthog.com/flags?v=2", {
291
+ method: "POST",
292
+ headers: { "Content-Type": "application/json" },
293
+ body: JSON.stringify({
294
+ api_key: environment.POSTHOG_PROJECT_TOKEN,
295
+ distinct_id: userId,
296
+ person_properties: { plan: request.user?.data?.plan },
297
+ }),
298
+ });
299
+
300
+ const data = await response.json();
301
+ // Cache the whole map: cache.put(`posthog:${userId}`, data.flags, 60)
302
+ // data.flags["new-checkout"] = { key, enabled, variant, metadata: { payload } }
303
+ const enabled = data.flags?.["new-checkout"]?.enabled === true;
304
+ const variant = data.flags?.["new-checkout"]?.variant; // multivariate flags
305
+ ```
306
+
307
+ Use `https://eu.i.posthog.com` if your PostHog project is hosted in the EU.
308
+
309
+ ### Flagsmith
310
+
311
+ Flagsmith's edge API evaluates flags for an identity with a simple GET. Use the
312
+ client-side environment key (not a server-side SDK key) — it's designed to be
313
+ public.
314
+
315
+ ```ts
316
+ const response = await fetch(
317
+ `https://edge.api.flagsmith.com/api/v1/identities/?identifier=${encodeURIComponent(userId)}`,
318
+ {
319
+ headers: { "X-Environment-Key": environment.FLAGSMITH_ENVIRONMENT_KEY },
320
+ },
321
+ );
322
+
323
+ const data = await response.json();
324
+ const flag = data.flags?.find((f) => f.feature.name === "new-checkout");
325
+ const enabled = flag?.enabled === true;
326
+ const value = flag?.feature_state_value; // remote config value
327
+ ```
328
+
329
+ ### Statsig, fully local
330
+
331
+ If you need many gates evaluated per request with zero provider calls, use
332
+ Statsig's `@statsig/serverless-client` SDK, which is built for short-lived
333
+ worker processes. Unlike the HTTP API examples above (which use the server
334
+ secret key), the serverless client evaluates on-device and authenticates with
335
+ the publishable client SDK key.
336
+
337
+ Zuplo runs a custom JavaScript engine rather than Node.js, so third-party
338
+ packages must be bundled into your project before you can import them — see
339
+ [Node Modules](../programmable-api/node-modules.mdx). Bundle the SDK once, then
340
+ import it from the bundled path:
341
+
342
+ ```bash
343
+ npm install @statsig/serverless-client
344
+ npx tsdown ./node_modules/@statsig/serverless-client --format esm --platform browser --out-dir ./modules/third-party/statsig
345
+ ```
346
+
347
+ Initialize the client once at module level so the configuration download happens
348
+ on cold start, not per request. Evaluate gates locally, and flush exposure
349
+ events with
350
+ [`context.waitUntil`](../programmable-api/zuplo-context.mdx#waituntil) so
351
+ analytics never add latency to a response:
352
+
353
+ ```ts title="modules/statsig-local-policy.ts"
354
+ import {
355
+ HttpProblems,
356
+ ZuploContext,
357
+ ZuploRequest,
358
+ environment,
359
+ } from "@zuplo/runtime";
360
+ import { StatsigServerlessClient } from "./third-party/statsig/index.mjs";
361
+
362
+ const client = new StatsigServerlessClient(environment.STATSIG_CLIENT_KEY);
363
+ // Kicks off the config download once per worker process, not per request
364
+ const ready = client.initializeAsync();
365
+
366
+ export default async function policy(
367
+ request: ZuploRequest,
368
+ context: ZuploContext,
369
+ ) {
370
+ await ready;
371
+ const enabled = client.checkGate("new-beta-endpoint", {
372
+ userID: request.user?.sub,
373
+ });
374
+ context.waitUntil(client.flush());
375
+
376
+ if (!enabled) {
377
+ return HttpProblems.forbidden(request, context, {
378
+ detail: "This feature is not enabled for your account",
379
+ });
380
+ }
381
+ return request;
382
+ }
383
+ ```
384
+
385
+ ### What about LaunchDarkly?
386
+
387
+ LaunchDarkly is the least HTTP-friendly option. Its server-side SDK holds a
388
+ persistent streaming connection open and relies on Node.js APIs that don't run
389
+ in Zuplo's engine, and LaunchDarkly doesn't document a plain-HTTP endpoint for
390
+ server-side evaluation. Its
391
+ [edge SDKs](https://launchdarkly.com/docs/sdk/server-side) evaluate locally but
392
+ assume platform-specific storage bindings (Cloudflare KV, Vercel Edge Config,
393
+ and similar), so they don't drop directly into a Zuplo project either. If
394
+ LaunchDarkly is your provider, the practical paths are evaluating flags in your
395
+ backend behind the gateway, or syncing flag state into a store your Zuplo code
396
+ reads with the patterns above.
397
+
398
+ ## Gate an MCP server with flags
399
+
400
+ If you're fronting an MCP server with the
401
+ [MCP Gateway](../mcp-gateway/introduction.mdx), the same policies apply — MCP
402
+ routes run the standard inbound policy chain before the handler. Add your
403
+ feature-gate policy to the MCP route to control access per user or plan, for
404
+ example to make MCP access a paid-tier feature or to turn off a beta server.
405
+
406
+ For curating _which tools_ a server exposes, start with the static
407
+ [capability filtering](../mcp-gateway/capability-filtering.mdx) policy, which
408
+ needs no code. Feature flags complement it when the availability of the server
409
+ itself must change dynamically per user without a redeploy.
410
+
411
+ ## Best practices
412
+
413
+ 1. **Decide how to fail.** If the provider is unreachable, fail closed (deny the
414
+ feature) for rollouts of risky functionality, or fail open (allow) for
415
+ cosmetic features. The examples above fail closed and log the error.
416
+ 2. **Keep per-user TTLs short.** 30–120 seconds balances provider traffic
417
+ against flag-change propagation. Global definitions can tolerate longer.
418
+ 3. **Cache the smallest useful value.** A boolean per gate per user stays well
419
+ within memory limits; don't cache whole provider responses you don't need.
420
+ Remember a Zuplo process has roughly 120 MB of memory — see
421
+ [Lazy Load Configuration](./lazy-load-configuration-into-cache.mdx) for the
422
+ caching trade-offs.
423
+ 4. **Store keys in environment variables.** Use secret
424
+ [environment variables](./environment-variables.mdx) for server keys like
425
+ Statsig's server secret; never hardcode them.
426
+ 5. **Log exposures in the background.** Providers use exposure events for
427
+ analytics and experiments. Send them with
428
+ [`context.waitUntil`](../programmable-api/zuplo-context.mdx#waituntil) (as in
429
+ the Statsig SDK example) so analytics never add latency to a request.
430
+
431
+ ## Next steps
432
+
433
+ - [BackgroundLoader](../programmable-api/background-loader.mdx) — the primitive
434
+ behind pattern 2
435
+ - [MemoryZoneReadThroughCache](../programmable-api/memory-zone-read-through-cache.mdx)
436
+ and [ZoneCache](../programmable-api/zone-cache.mdx) — the caching layers
437
+ - [Custom code policies](../policies/custom-code-inbound.mdx) — how inbound
438
+ policies are wired and run
439
+ - [Lazy Load Configuration](./lazy-load-configuration-into-cache.mdx) — the
440
+ general config-caching pattern this guide builds on
441
+ - [Curate the tools an upstream exposes](../mcp-gateway/how-to/curate-tools.mdx)
442
+ — static MCP tool curation to combine with flags
@@ -3,12 +3,12 @@ title: Secure a GCP Backend with Zuplo Upstream Auth
3
3
  sidebar_label: GCP Backend
4
4
  ---
5
5
 
6
- When using any API gateway as your API's entry point, it's critical that only
7
- traffic that originates from the Gateway is allowed to call your backend. There
6
+ When using any gateway as your API's entry point, it's critical that only
7
+ traffic that originates from the gateway is allowed to call your backend. There
8
8
  are [many way to this](./securing-your-backend.mdx) depending on your
9
9
  requirements and how your backend is hosted. This article will explain how to
10
10
  use Google IAM to secure a GKE cluster so that only requests made through your
11
- Zuplo API Gateway will be allowed to call your GKE ingress.
11
+ Zuplo Gateway will be allowed to call your GKE ingress.
12
12
 
13
13
  Using GCP IAM to authorize your Zuplo Gateway to make requests to your backend
14
14
  utilizes Googles core IAM system known as
@@ -33,11 +33,11 @@ set up behind an HTTP Load Balancer can be used.
33
33
  The diagram below shows how the end-to-end system interacts. The important steps
34
34
  to this process are:
35
35
 
36
- 1. The client makes a request to your Zuplo API Gateway
37
- 1. The Zuplo API Gateway enforces any policies (for example authentication,
36
+ 1. The client makes a request to your Zuplo Gateway
37
+ 1. The Zuplo Gateway enforces any policies (for example authentication,
38
38
  authorization, rate limiting)
39
- 1. The Zuplo API Gateway proxies the request to the public IP address of your
40
- GCP Load Balancer. Zuplo adds authorization information to the request that
39
+ 1. The Zuplo Gateway proxies the request to the public IP address of your GCP
40
+ Load Balancer. Zuplo adds authorization information to the request that
41
41
  identify the request as coming from Zuplo
42
42
  1. GCP Identity Aware proxy validates that the request comes from an authorized
43
43
  Service Account identity. Unauthorized requests are rejected.
@@ -2,19 +2,19 @@
2
2
  title: Health Check Handler
3
3
  sidebar_label: Health Checks
4
4
  description:
5
- Learn how to set up health check endpoints to monitor your API Gateway and
5
+ Learn how to set up health check endpoints to monitor your Zuplo Gateway and
6
6
  backend services.
7
7
  tags:
8
8
  - observability
9
9
  - backends
10
10
  ---
11
11
 
12
- Part of running a reliable API Gateway is ensuring that the service is healthy
12
+ Part of running a reliable Zuplo Gateway is ensuring that the service is healthy
13
13
  and available. With Zuplo, it's easy to set up a health check endpoint that can
14
14
  be used to ensure the health of both your Zuplo Gateway and your backend (as
15
15
  well as the connectivity between them).
16
16
 
17
- A typical health check endpoint on your API Gateway will exercise some of the
17
+ A typical health check endpoint on your Zuplo Gateway will exercise some of the
18
18
  most important policies (such as authentication) and then make a simple request
19
19
  to your backend to ensure that it's reachable and functioning.
20
20
 
@@ -32,7 +32,7 @@ OpenAPI file this would look like:
32
32
  "/health": {
33
33
  "get": {
34
34
  "summary": "Health Check",
35
- "description": "Checks the health of the API Gateway and backend.",
35
+ "description": "Checks the health of the Zuplo Gateway and backend.",
36
36
  "responses": {
37
37
  "200": {
38
38
  "description": "OK"
@@ -32,7 +32,7 @@ your service hosted to meet any sovereignty or data residency concerns.
32
32
 
33
33
  Managed Dedicated is ideal for organizations that need:
34
34
 
35
- - To run your API Gateway on a specific cloud provider
35
+ - To run your Zuplo Gateway on a specific cloud provider
36
36
  - Custom networking configurations, such as restricting access to the public
37
37
  internet
38
38
  - Geographical deployment requirements where Managed Edge isn't feasible
@@ -50,7 +50,7 @@ Run Zuplo on your own infrastructure in any cloud or private data center. Zuplo
50
50
  Self-Hosted runs exclusively on Kubernetes and is installed with a single Helm
51
51
  chart into your cluster.
52
52
 
53
- In the standard hybrid deployment model, you run the Zuplo API Gateway and its
53
+ In the standard hybrid deployment model, you run the Zuplo Gateway and its
54
54
  management plane on your Kubernetes cluster, while a small set of Zuplo cloud
55
55
  services provides supporting features such as deployment configuration and API
56
56
  key management. All API traffic to your gateways stays on your infrastructure.
@@ -5,7 +5,7 @@ sidebar_label: Environment variables
5
5
 
6
6
  For security reasons, your local development doesn't have access to the
7
7
  environment variables that you have configured on the Zuplo Portal. Instead,
8
- your local Zuplo API Gateway will load environment variables from a .env file.
8
+ your local Zuplo Gateway will load environment variables from a .env file.
9
9
 
10
10
  1. Create a .env file in the root of your project.
11
11
  2. Follow the following format
@@ -28,7 +28,7 @@ Zuplo supports the following metrics:
28
28
 
29
29
  - request latency
30
30
  - This measures the total time (in milliseconds) that a request takes once it
31
- has entered the API Gateway. It includes any outbound calls from the
31
+ has entered the Zuplo Gateway. It includes any outbound calls from the
32
32
  gateway.
33
33
  - request content length
34
34
  - The content length of the request as reported by the content-length header.
@@ -3,7 +3,7 @@ title: Migrate to Zuplo from Other API Gateways
3
3
  sidebar_label: Migration Overview
4
4
  ---
5
5
 
6
- Moving to Zuplo from another API gateway is straightforward. Zuplo is
6
+ Moving to Zuplo from another gateway is straightforward. Zuplo is
7
7
  OpenAPI-native, so you can import your existing API definitions and start
8
8
  configuring policies in minutes. This section provides migration guides for the
9
9
  most common API gateways.
@@ -2,18 +2,18 @@
2
2
  title: Deploying Zuplo from a Monorepo
3
3
  sidebar_label: Monorepo Deployment
4
4
  description:
5
- "Deploy a Zuplo API gateway from a monorepo subdirectory using the Zuplo CLI
6
- and GitHub Actions."
5
+ "Deploy a Zuplo Gateway from a monorepo subdirectory using the Zuplo CLI and
6
+ GitHub Actions."
7
7
  ---
8
8
 
9
- If your Zuplo API gateway lives inside a monorepo alongside other services, you
10
- can deploy it using the [Zuplo CLI](../cli/overview.mdx) and your CI/CD
11
- provider. Zuplo's
12
- [built-in GitHub integration](./source-control-setup-github.mdx) connects each
13
- project to a dedicated repository and deploys automatically on every push.
14
- Because it doesn't natively support projects located in a subdirectory, you need
15
- to use the Zuplo CLI with a [custom CI/CD pipeline](./custom-ci-cd.mdx) to
16
- deploy from the correct directory.
9
+ If your Zuplo Gateway lives inside a monorepo alongside other services, you can
10
+ deploy it using the [Zuplo CLI](../cli/overview.mdx) and your CI/CD provider.
11
+ Zuplo's [built-in GitHub integration](./source-control-setup-github.mdx)
12
+ connects each project to a dedicated repository and deploys automatically on
13
+ every push. Because it doesn't natively support projects located in a
14
+ subdirectory, you need to use the Zuplo CLI with a
15
+ [custom CI/CD pipeline](./custom-ci-cd.mdx) to deploy from the correct
16
+ directory.
17
17
 
18
18
  This guide covers the project structure requirements, CI/CD configuration, local
19
19
  development, and common troubleshooting steps for monorepo setups.
@@ -1,17 +1,18 @@
1
1
  ---
2
- title: Performance Testing Your API Gateway
2
+ title: Performance Testing Your Gateway
3
3
  sidebar_label: Performance Testing
4
4
  ---
5
5
 
6
6
  <!-- vale Vale.Spelling["Blazemeter","JMeter","wrk"] = NO -->
7
7
 
8
8
  Performance testing is critical for understanding the real-world performance of
9
- your API when using an API gateway like Zuplo. This guide helps you create fair
10
- and accurate performance tests that properly measure latency and throughput.
9
+ your API when using a unified gateway like Zuplo. This guide helps you create
10
+ fair and accurate performance tests that properly measure latency and
11
+ throughput.
11
12
 
12
13
  ## Creating Fair Comparison Tests
13
14
 
14
- When evaluating API gateway performance, it's essential to ensure your tests
15
+ When evaluating gateway performance, it's essential to ensure your tests
15
16
  accurately reflect real-world conditions and provide a fair comparison between
16
17
  direct backend calls and calls through your gateway.
17
18
 
@@ -53,7 +54,7 @@ traffic experiences significantly higher jitter (variance), making response
53
54
  times less predictable.
54
55
 
55
56
  This artificial performance boost from testing within the same cloud provider
56
- can make it appear that an API gateway adds substantially more latency than it
57
+ can make it appear that a gateway adds substantially more latency than it
57
58
  actually does in real-world scenarios where traffic crosses network boundaries.
58
59
 
59
60
  ### Ensure Test Equality
@@ -106,14 +107,14 @@ impact in your analysis.
106
107
 
107
108
  ## Understanding Gateway Latency
108
109
 
109
- API gateways necessarily add some latency to process requests. For Zuplo:
110
+ Gateways necessarily add some latency to process requests. For Zuplo:
110
111
 
111
112
  - **Base latency:** Approximately 20-30ms with no policies
112
113
  - **Per policy:** Most policies add 1-5ms each
113
114
  - **Complex policies:** Authentication, rate limiting, or custom code can add
114
115
  5-15ms
115
116
 
116
- This latency is the trade-off for the benefits an API gateway provides:
117
+ This latency is the trade-off for the benefits a gateway provides:
117
118
 
118
119
  - Centralized authentication and authorization
119
120
  - Rate limiting and quota management
@@ -299,7 +300,7 @@ Managed Dedicated, Zuplo can be deployed directly to:
299
300
 
300
301
  This deployment model provides:
301
302
 
302
- - **Minimal latency:** Your API gateway runs in the same cloud network as your
303
+ - **Minimal latency:** Your gateway runs in the same cloud network as your
303
304
  backend
304
305
  - **Predictable performance:** Consistent sub-10ms latency for intra-region
305
306
  traffic
@@ -364,7 +365,7 @@ periods.
364
365
  ## Summary
365
366
 
366
367
  Creating fair performance tests requires careful attention to test conditions,
367
- understanding of network topology, and realistic expectations about API gateway
368
+ understanding of network topology, and realistic expectations about gateway
368
369
  overhead. By following these guidelines, you'll get accurate measurements that
369
370
  help you make informed decisions about your API architecture.
370
371
 
@@ -4,7 +4,7 @@ sidebar_label: Azure Blob
4
4
  ---
5
5
 
6
6
  This plugin pushes request/response logs to Azure Blob Storage. This can be used
7
- to save request data generated by your API Gateway to use for monitoring,
7
+ to save request data generated by your Zuplo Gateway to use for monitoring,
8
8
  analytics, auditing, or debugging purposes.
9
9
 
10
10
  <EnterpriseFeature name="Custom logging" />
@@ -4,8 +4,8 @@ sidebar_label: Azure Event Hubs
4
4
  ---
5
5
 
6
6
  This plugin pushes request/response logs to Azure Event Hubs. This can be used
7
- to stream the request data generated by your API Gateway to use for monitoring,
8
- analytics, auditing, or debugging purposes.
7
+ to stream the request data generated by your Zuplo Gateway to use for
8
+ monitoring, analytics, auditing, or debugging purposes.
9
9
 
10
10
  <EnterpriseFeature name="Custom logging" />
11
11