# Compatibility Dates

Zuplo is constantly shipping updates to the underlying runtime of projects.
Occasionally, these updates aren't backwards compatible. In order to ensure that
your project continues to build, deploy, and operate as you expect, you can set
a compatibility date to lock in the behavior and APIs of the runtime.

The compatibility date is set in the `zuplo.jsonc` file at the root of your
project. The `zuplo.jsonc` file is created by default for new projects and
contains the default configuration. For more information on the `zuplo.jsonc`
file, see the [Zuplo Project Configuration](./zuplo-json.mdx) documentation.

## 2026-03-01

:::note

This compatibility date is the default for projects created after March
1st, 2026. Existing projects should update their `zuplo.jsonc` to take advantage
of this change.

:::

### Chain Response Sending Hooks

This compatibility date changes how response sending hooks behave when multiple
hooks are registered. With this flag enabled, response sending hooks
(`context.addResponseSendingHook` and `runtime.addResponseSendingHook`) chain
properly, where each hook receives the response from the previous hook instead
of the original response.

**Before this flag:** All hooks received the **_original_** response, so only
the last hook's output was used.

**After this flag:** Hooks are chained properly, each receiving the **_previous
hook's response_**. For example, if you register three hooks A, B, and C in a
policy in that order, hook A's response passes to hook B, then hook B's response
passes to hook C.

This change enables more predictable behavior when composing multiple response
transformations.

### 501 for Unsupported HTTP Methods

This compatibility date changes how unsupported HTTP methods are handled.
Requests using non-standard HTTP methods such as WebDAV methods (`PROPFIND`,
`MKCOL`, `COPY`, etc.) now return a proper `501 Not Implemented` response
instead of a `500 Internal Server Error`.

**Before this flag:** Unsupported HTTP methods returned a
`500 Internal Server Error`.

**After this flag:** Unsupported HTTP methods return a `501 Not Implemented`
response with an [RFC 7807](https://www.rfc-editor.org/rfc/rfc7807)
`application/problem+json` body.

## 2025-02-06

This compatibility date introduces a number of breaking changes to improve the
overall behavior of Zuplo APIs. This compatibility date is the default for any
projects created after 2025-03-27.

### Special Characters in OpenAPI Format URLs

Previously, special characters that were included in URLs that used the
`open-api` formatted URLs weren't escaped. This allowed an unintended behavior
where the URL could include Regex patterns even though the OpenAPI format URLs
doesn't allow regex. This has been fixed and now all special characters are
escaped. This allows URLs with formats like:

```
/accounts/open({id})
/accounts/:action
```

### Removed legacy Log Initialization

Previously, several of the Zuplo log plugins could be enabled by setting
undocumented environment variables. This was a legacy feature that was added
before the current plugin system existed. This feature has been removed. Log
plugins should be enabled using the
[documented plugin system](../articles/logging.mdx).

If you are setting any of the following environment variables, you should
migrate to the log plugin initialization.

```txt
GCP_USER_LOG_NAME
GCP_USER_LOG_SVC_ACCT_JSON
ZUPLO_USER_LOGGER_DATA_DOG_URL
```

### Removed legacy Log Context

Previously, several log plugins used special properties on `context.custom` to
set global attributes on logs. This was a legacy feature that was added before
the current plugin system existed. This feature has been removed. Log plugins
should be enabled using the [documented plugin system](../articles/logging.mdx).

If you are setting any of the following in your code, you should migrate to the
plugin configuration instead.

```ts
context.custom["__ddtags"]; // Sets tags
context.custom["__ddattr"]; // Sets fields
```

Migrate to the following:

```ts
export function runtimeInit(runtime: RuntimeExtensions) {
  runtime.addPlugin(
    new DataDogLoggingPlugin({
      url: "https://http-intake.logs.datadoghq.com/api/v2/logs",
      apiKey: environment.DATADOG_API_KEY,
      source: "MyAPI", // Optional, defaults to "Zuplo"
      tags: {
        tag: "hello",
      },
      fields: {
        field1: "value1",
        field2: "value2",
      },
    }),
  );
}
```

### Improved Node.js Compatibility

The Zuplo runtime doesn't run Node.js, but is compatible with a number of
Node.js APIs. This compatibility date adds some additional support for Node.js
specific APIs.

### URL Forward Handler Redirects

The `UrlForwardHandler` now supports the `followRedirects` option. Previously,
this option wasn't supported on the forward handler. However, it was erroneously
documented as supported. This property is behind a compatibility date in order
to ensure that if existing projects were using the option that didn't work as
expected, they wouldn't be broken by this change.

## 2024-09-02

The compatibility date allows the ability to call `fetch` to hosts with custom
ports. Previously only the standard ports (80, 443) were allowed.

## 2024-03-14

This compatibility date doesn't include any breaking changes. However, Zuplo
made a number of changes to the runtime build process. These changes will allow
a number of future improvements. Out of an abundance of caution, these changes
are only enabled for projects that have set their compatibility date to
`2024-03-14`. This compatibility date is the default for any projects created
after March 14th, 2024.

Over time, the build changes will be enabled by default on all future
deployments regardless of compatibility date. Existing customers are encouraged
to update their compatibility date to `2024-03-14` and test their projects to
ensure that they continue to operate as expected.

This new build process has rolled out to all customers regardless of
compatibility date.

## 2024-01-15

This compatibility date includes several breaking changes to improve the overall
behavior of Zuplo APIs. This compatibility date is the default for any projects
created after Jan. 15th, 2024.

### Run Outbound Policies on All Responses

Previously, outbound policies would only run on response status ranging from
200-299. Now outbound policies will always run, regardless of the response code.

### No Hooks on System Routes

Previously runtime hooks such as `OnRequest` or `OnResponseSending` would run on
system routes. For example, if you are using our Developer Portal and have it
running on `/docs`, before this change you could write a hook that modified the
output of the Developer Portal. This could result in unexpected behavior and is
now disallowed.

### Remove Cloudflare Location Headers

On SaaS deployments, Zuplo routes all requests through Cloudflare. Cloudflare
adds a number of headers to requests. Previously, some Cloudflare location
headers (for example `cf-ipregion`) could be passed through your Zuplo gateway.
Now these headers are always removed from the outbound request if they have been
set. If you need access to geo-location data use
[`context.incomingRequestProperties`](./zuplo-context.mdx) instead.

### Remove Internal Zuplo Headers

Zuplo uses several internal headers to send data between different layers of our
systems. Previously, some of these headers where exposed in a way that they
could be accessed directly. Examples were `zp-ipcity` and `zp-ipcountry`. These
headers are now always removed from the outbound request if they have been set.
If you need access this data use
[`context.incomingRequestProperties`](./zuplo-context.mdx) instead.
