Docs

API7 Gateway 3.10.3

Several Data Plane shared memory (lua_shared_dict) defaults were raised, so a 3.10.3 gateway reserves about 365 MiB more shared memory at startup than 3.10.2 with the default configuration:

Release Date: 2026-07-14

Upgrade Notes

Upgrade note — higher default gateway memory usage

Several Data Plane shared memory (lua_shared_dict) defaults were raised, so a 3.10.3 gateway reserves about 365 MiB more shared memory at startup than 3.10.2 with the default configuration:

Shared dictionary3.10.2 default3.10.3 default
prometheus-metrics (advanced metrics)15 MiB128 MiB
kubernetes, nacos, nacos-stream, consul (service discovery)20 MiB each64 MiB each
tracing_buffer (SkyWalking)10 MiB32 MiB
api-calls-for-portal10 MiB64 MiB

These dictionaries are allocated when the gateway starts, whether or not the corresponding feature is in use, so the increase applies to every 3.10.3 gateway. Before upgrading, raise the gateway container's memory requests and limits (in Kubernetes, also review node memory-pressure and eviction thresholds) so the gateway is not OOM-killed. If you do not use a given feature — for example a service discovery type you have not configured — you can lower its dictionary back toward the previous value through the gateway configuration, or through the shared-dict values in the Helm chart.

Upgrade note — built-in user login policy is stricter

Built-in Dashboard users are now temporarily locked out after repeated failed password attempts. The default policy is enabled, bans the user and source IP after 5 consecutive failures, and lasts 15 minutes. Administrators can tune or disable it through the new login failure restriction system setting. New passwords and passwords changed after upgrade must also be at least 12 characters and still satisfy the existing complexity requirements. Existing passwords are not revalidated at sign-in.

If a built-in user enables two-factor authentication, HTTP Basic Auth for that user is rejected because Basic Auth cannot provide a second factor. Use access tokens for programmatic integrations instead; token authentication is sent with the X-API-KEY header and does not require a 2FA verification code.

Upgrade note — forwarded headers are trusted only from trusted addresses

The gateway now uses apisix.trusted_addresses to decide whether client-supplied X-Forwarded-* and RFC 7239 Forwarded headers are trusted. When trusted_addresses is not configured, or when the request comes from an untrusted address, the gateway overwrites X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-Port with gateway-observed values and clears the Forwarded header before proxying upstream. If an upstream application depends on the original forwarded protocol, host, or port sent by a trusted load balancer or reverse proxy, configure that proxy's IP or CIDR in trusted_addresses.

Upgrade note — OpenID Connect silent re-authentication is no longer enabled by default

The openid-connect plugin no longer sets refresh_session_interval to 900 seconds by default. Periodic silent re-authentication now happens only when refresh_session_interval is explicitly configured. If your deployment relied on the previous 900-second refresh behavior, set refresh_session_interval: 900 before or during the upgrade.

Upgrade note — SQL Server deployments enable snapshot reads on first startup

For SQL Server-backed deployments, the Control Plane now creates and prepares the database before other components connect, and enables READ_COMMITTED_SNAPSHOT to prevent gateway configuration reads from blocking behind writes. On an existing SQL Server database where this setting is still disabled, the first startup applies the database-level change with ROLLBACK IMMEDIATE; in-flight database transactions and sessions can be disconnected once, after which connection pools reconnect and later starts are no-ops.

Upgrade note — additional plugin secret fields are encrypted at rest

The Control Plane now encrypts additional credential-bearing plugin fields at rest. Because API7 EE upgrades the Control Plane before the Data Plane, during the upgrade window a 3.10.3 Control Plane encrypts these fields while an older 3.10.2 Data Plane cannot decrypt them, which can cause the affected plugins to fail until the Data Plane is also upgraded.

The newly encrypted fields, by plugin, are:

  • ai-cache: semantic.embedding.openai.api_key, semantic.embedding.azure_openai.api_key

If you use any of these plugins with the listed fields, upgrade the Data Plane to 3.10.3 promptly after the Control Plane, and avoid editing those plugins until both sides are on 3.10.3.

Features

Plugins

Data Plane

  • Added apisix.trusted_addresses, which controls whether the gateway trusts client-supplied X-Forwarded-* and Forwarded headers based on the resolved client address.
  • Added apisix.match_uri_encoded_slash. When enabled, an encoded slash (%2F) stays encoded during route matching so it can be treated as part of a path parameter instead of a path separator.
  • In standalone YAML mode, environment-variable placeholders are now resolved before YAML parsing. Unquoted placeholders can become native booleans or numbers, while quoted placeholders stay strings, preserving large IDs and token values exactly.

Control Plane

  • Added TOTP two-factor authentication for built-in Dashboard users. Users can enroll, enable, disable, and recover 2FA from their account settings, and administrators can reset a user's 2FA state.
  • Added login failure restriction for built-in users. Repeated failed logins temporarily lock the user and source IP, emit an audit event, and return a clear lockout message.
  • Added the Dashboard UI for two-factor authentication: account setup with QR code and recovery codes, an OTP step during login, and an administrator action to reset a user's 2FA state.
  • Updated password forms and generated passwords to use the new 12-character minimum length.

Developer Portal

  • Added an option to require two-factor authentication. When 2FA is enabled and twoFactor.required is set, developers must complete 2FA enrollment before they can access protected pages, and the requirement is enforced both at sign-in and at the proxy layer.

Fixes

Plugins

  • AI Proxy (opens in Plugin Hub docs) and AI Proxy Multi (opens in Plugin Hub docs)
    • Fixed issue: Anthropic Messages requests that contained tool results mixed with other content could be converted into an invalid OpenAI Chat message order, causing OpenAI-compatible upstreams to reject every later request in the session. Tool messages are now emitted immediately after the assistant tool-call message, and adjacent text or media is preserved in a following user message. Several other Anthropic-to-OpenAI conversion details were aligned with LiteLLM-compatible behavior, including tool name sanitization, long tool-name collision handling, adaptive thinking effort, structured-output schema extraction, empty array encoding, and content block shaping.
    • Fixed issue: Structured chat content could reach downstream AI plugins as a table and cause request processing errors. Protocol adapters now flatten text content consistently before AI guard and cache plugins consume it.
  • AI Lakera Guard (opens in Plugin Hub docs)
    • Fixed issue: In streaming responses with action: alert and fail_open: false, a Lakera API error or timeout could let the streamed response through instead of failing closed. Lakera errors are now handled according to fail_open, so a strict configuration blocks the response.
  • AI AWS Content Moderation (opens in Plugin Hub docs) and AI Aliyun Content Moderation (opens in Plugin Hub docs)
    • Fixed issue: deny_code accepted arbitrary numbers. It is now validated as an integer HTTP status code in the 200–599 range (default 200), so an out-of-range value is rejected at configuration time.
  • AI Aliyun Content Moderation (opens in Plugin Hub docs)
    • Fixed issue: Returning ngx.OK from the body filter could interrupt later body-filter processing. The plugin now returns normally so other filters can continue.
  • AI Rate Limiting (opens in Plugin Hub docs)
    • Fixed issue: Some configured Redis fields were dropped and replaced with defaults — redis_username/redis_password for the redis-sentinel policy and redis_keepalive_timeout/redis_keepalive_pool for the redis and redis-cluster policies. All configured Redis fields are now forwarded.
  • gRPC Transcode (opens in Plugin Hub docs)
    • Fixed issue: Empty protobuf repeated fields were encoded as {} instead of JSON arrays ([]). Empty repeated fields now appear as arrays, including nested and descriptor-set based messages.
  • Key Auth (opens in Plugin Hub docs) and other consumer authentication plugins
    • Fixed issue: If a consumer credential referenced a secret that could not be resolved, the Data Plane could still index the unresolved literal value and authenticate requests with it. Consumer authentication now fails closed when a referenced secret cannot be resolved.
  • Secret references
    • Fixed issue: Updates or deletions of /secrets configuration did not invalidate the secret LRU cache, so old secret values could continue to be used until cache expiry or indefinitely. Secret references are now re-resolved after secret configuration changes.
  • Proxy Rewrite (opens in Plugin Hub docs)
    • Fixed issue: With use_real_request_uri_unsafe and uri configured together, the request query string was dropped during URI rewriting. The original query string is now preserved and correctly merged when the rewritten URI already contains a query.
  • Loggly
    • Fixed issue: Batched Loggly entries from different routes could use the wrong token or tags because the async handler reused the latest route configuration. Each batch processor now keeps its own route configuration.
  • Datadog (opens in Plugin Hub docs)
    • Fixed issue: Large coalesced DogStatsD datagrams could exceed the common 8192-byte agent buffer and be silently truncated. The plugin now coalesces only when the payload fits, otherwise it falls back to one datagram per metric.
  • Zipkin (opens in Plugin Hub docs)
    • Fixed issue: Requests explicitly marked as unsampled still built full span tag tables and access-phase child spans. Unsampled requests now skip that extra tracing work while preserving trace propagation.
  • OpenTelemetry (opens in Plugin Hub docs)
    • Fixed issue: Updating OpenTelemetry plugin metadata at runtime did not rebuild the tracer used for injected core spans, so those spans could keep using stale collector or resource settings until worker recycle. The tracer now refreshes when metadata changes.
    • Fixed issue: additional_attributes were evaluated before log-phase variables were populated, so attributes that depend on final request state could be missing or stale. They are now evaluated in the log phase.
    • Fixed issue: With trace_id_source set to x-request-id, an X-Request-Id value that is not valid hexadecimal (for example a UUID), or a duplicated header, could return HTTP 500. The value is now validated and the plugin falls back to a random valid trace ID when it cannot be used.
    • Fixed issue: The plugin metadata schema accepted non-scalar values for resource attributes and collector.request_headers, which were then silently dropped at runtime. Such values are now rejected at configuration time.
  • OpenID Connect (opens in Plugin Hub docs)
    • Fixed issue: refresh_session_interval incorrectly defaulted to 900, enabling silent re-authentication even when users did not configure it. The default is removed (see Upgrade Notes).
  • MQTT Proxy (opens in Plugin Hub docs)
    • Fixed issue: protocol_name was required even though the standard default is MQTT. It is now optional and defaults to MQTT.
  • Forward Auth (opens in Plugin Hub docs)
    • Fixed issue: When request_method was POST, the authorization request could forward the client's Transfer-Encoding, Content-Length, and Expect headers after the body had already been buffered, producing inconsistent request framing. These client framing headers are no longer copied to the auth service.
  • Authz CASBIN
    • Fixed issue: Routes using different Casbin model or policy shapes could trigger casbin enforce error / invalid request size after switching between them. The bundled lua-casbin dependency is updated to include the enforcement fixes.
  • Request ID (opens in Plugin Hub docs)
    • Fixed issue: Configuring algorithm: range_id without the optional range object could return HTTP 500. The range object now has a default value.
  • Workflow (opens in Plugin Hub docs)
    • Fixed issue: Workflow action plugins could run _meta.pre_function hooks before workflow skipped or executed the action, changing behavior even for actions that should not run. Workflow now decides whether to run the action before executing those meta hooks.
  • Request Validation (opens in Plugin Hub docs)
    • Fixed issue: A form body whose Content-Type carried a charset parameter or different casing (for example application/x-www-form-urlencoded; charset=utf-8) was not recognized as form-urlencoded, so it was parsed as JSON and rejected with HTTP 400. Such content types are now recognized and validated as form bodies.

Data Plane

  • Fixed issue: Log rotation could leave some log files open after only part of the file set was rotated. The gateway now reopens logs correctly after partial rotation.
  • Fixed issue: When the configuration source reported a smaller revision than the gateway had already seen (for example after the Control Plane database was restored to an earlier state), the gateway could keep serving stale configuration until a worker restart. It now forces a full configuration resync when a smaller revision is observed.
  • Fixed issue: A plugin attached through a global rule or a consumer (such as ai-proxy-multi) could fail with HTTP 5xx because the gateway could not fetch the plugin's parent configuration at request time. All plugin-bearing resource types are now resolved correctly.
  • Fixed issue: With client-control configured with max_body_size: 0 (no limit), a chunked request body could still be rejected with HTTP 413. A max_body_size of 0 now correctly disables the size check for chunked requests.

Control Plane

  • Fixed issue: Gateway instances could be marked OutOfSync for a short window immediately after a configuration revision changed, before the next heartbeat reported the new revision. A grace period now keeps recently heartbeating instances Healthy during that normal synchronization window.
  • Fixed issue: Compatibility reports were capped at 200 unordered items, so large reports could hide errors and differ between gateway instances. The Control Plane now stores the full sorted report and computes compatibility from all items.
  • Fixed issue: A secret provider request body could match a different provider type than the provider named in the URL path, causing the Data Plane to discard or misread the stored secret. The Control Plane now validates the body against the selected provider type.
  • Fixed issue: The Control Plane accepted some core resource configurations that the Data Plane silently discarded, including invalid TLS, filter, and IP match configurations. These are now rejected by validation before publishing.
  • Fixed issue: Plugin configurations on the runtime services endpoint were not validated, so a service with an invalid plugin configuration was accepted and then silently discarded by the Data Plane. Service plugin configurations are now validated and rejected with HTTP 400 when invalid.
  • Fixed issue: IPv6 upstream node hosts were rejected by the OpenAPI schema. IPv6 hosts are now accepted.
  • Fixed issue: Batch ssls validation used the SNI schema instead of the SSL schema, so entries without required certificate fields could pass validation. Batch SSL validation now uses the correct schema.
  • Fixed issue: Audit log export returned only the first 256 rows. Exports now include all matching audit logs.
  • Fixed issue: Credential lookup indexes could be dropped by components that do not run database migration, and some startup schema repairs rebuilt current indexes unnecessarily. Schema repair now keeps current indexes and repairs only stale shapes.
  • Fixed issue: Heartbeat and instance status queries could become slow on large deployments. Additional indexes and Go-side status computation improve these lookups.