import Issues from '../../getting-started/issues.md';

# Configuration

Platformatic Gateway can be configured with a [configuration file](#configuration-files) in the different file formats below. The Gateway also supports use of environment variables as setting values with [environment variable placeholders](../gateway/configuration.md#setting-and-using-env-placeholders).

## Configuration Files

Platformatic will automatically detect and load configuration files found in the current working directory with the file names listed [here](../../file-formats.md#configuration-files).

## Supported File Formats

For detailed information on supported file formats and extensions, visit our [Supported File Formats and Extensions](../../file-formats.md#supported-file-formats) page

## Configuration Settings

Configuration file settings are grouped as follows:

- **`basePath`** **(required)**: Configures the [basePath](../service/configuration.md#basePath).
- **`server`** **(required)**: Configures the [server settings](../service/configuration.md#server)
- **`gateway`**: Specific settings for Platformatic Gateway, such as application management and API composition.
- **`plugins`**: Manages additional functionality through [plugins](../service/configuration.md#plugins).
- **`telemetry`**: Handles [telemetry data reporting](../service/configuration.md#telemetry).
- **`watch`**: Observes file changes for [dynamic updates](../service/configuration.md#watch).

Sensitive data within these settings should use [configuration placeholders](#configuration-placeholders) to ensure security.

### Gateway

Configure `@platformatic/gateway` specific settings such as `applications` or `refreshTimeout`:

- **`applications`** (`array`, default: `[]`) — is an array of objects that defines
  the applications managed by the gateway. Each application object supports the following settings:
  - **`id`** (**required**, `string`) - A unique identifier for the application. Use a Platformatic Runtime application id if the application is executing inside [Platformatic Runtime context](../runtime/overview.md#platformatic-runtime-context).
  - **`origin`** (`string`) - A service origin. Skip this option if the service is executing inside [Platformatic Runtime context](../runtime/overview.md#platformatic-runtime-context). In this case, application `id` will be used instead of origin.
  - **`openapi`** (`object`) - The configuration file used to compose [OpenAPI](#openapi) specification.
  - **`graphql`** (`object`) - The configuration for the [GraphQL](#graphql) application.
  - **`proxy`** (`object` or `false`) - Service proxy configuration. If `false`, the application proxy is disabled. Supports the following options:
    - **`prefix`** (`string`) - Service proxy prefix. All application routes will be prefixed with this value.
    - **`rewritePrefix`** (`string`) - Rewrite the prefix to the specified string before sending to the upstream. The default is determined by the target capability.
    - **`rewriteLocationHeader`** (`boolean`) - Controls rewriting of relative `Location` response headers from the upstream. When enabled, the gateway rewrites redirects from `rewritePrefix` to `prefix`. Set to `false` to forward relative `Location` headers unchanged. The default is `true` unless overridden by the target capability.
    - **`methods`** (`array of string`, default: `['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']`) - HTTP methods handled by this proxy application. Useful when multiple applications share the same `prefix` and need method-based routing.

      :::note
      `HEAD` is not part of the configurable list. It is implicitly handled when a matching `GET` route exists.
      :::

    - **`routes`** (`array of string`, default: `['/', '/*']`) - Route patterns handled by this proxy application. Useful when multiple applications share the same `prefix` and need path-based routing. Route patterns follow Fastify route syntax for parameters and wildcards (for example, `/users/:id` and `/public/*`). See the [Fastify route URL syntax documentation](https://fastify.dev/docs/latest/Reference/Routes/#url-building) for details.
    - **`hostname`** (`string`) - An additional domain name this application is reachable at. It will be matched against requests' `Host` header. When a hostname is specified, the service is accessible without the prefix when the Host header matches.
    - **`upstream`** (`string`) - The origin URL to proxy requests to. Required for external services. Not needed for Platformatic Runtime applications where the application `id` is used; will be ignored when using `custom.getUpstream`.
    - **`ws`** (`object`) - WebSocket proxy configuration. Supports the following options:
      - **`upstream`** (`string`, **required**) - The WebSocket upstream URL (e.g., `ws://localhost:3000`).
      - **`reconnect`** (`object`) - WebSocket reconnection settings:
        - **`pingInterval`** (`number`) - Interval in milliseconds between ping messages to keep the connection alive.
        - **`maxReconnectionRetries`** (`number`) - Maximum number of reconnection attempts.
        - **`reconnectInterval`** (`number`) - Initial delay in milliseconds between reconnection attempts.
        - **`reconnectDecay`** (`number`) - Multiplier for the reconnection interval on each retry.
        - **`connectionTimeout`** (`number`) - Timeout in milliseconds for establishing a connection.
        - **`reconnectOnClose`** (`boolean`) - Whether to reconnect when the connection is closed.
        - **`logs`** (`boolean`) - Enable logging for WebSocket reconnection events.
      - **`hooks`** (`object`) - WebSocket hooks configuration:
        - **`path`** (`string`) - Path to a JavaScript/TypeScript file that exports WebSocket lifecycle hooks (e.g., `onConnect`, `onReconnect`, `onDisconnect`, `onIncomingMessage`, `onOutgoingMessage`, `onPong`).
    - **`custom`** (`object`) - Custom proxy logic configuration. This is a supported public API: external modules and addons can rely on this contract to implement per-request routing, for example to route requests to different versions of the same application based on a header or a cookie. Supports the following options:
      - **`path`** (**required**, `string`) - Path to a JavaScript/TypeScript file that exports the custom proxy hooks. The module can either export the hooks object directly (as the default export) or export a factory function `(options) => hooks` (synchronous or asynchronous) which receives the `options` value below and returns the hooks object.
      - **`options`** (`object`) - An arbitrary JSON object which is passed to the factory function exported by the module referenced in `path`. It is ignored when the module exports the hooks object directly.

      The hooks object supports the following properties, all optional:

      - **`preRewrite`** (`function`) - A function `(url, params, prefix) => string` that can be used to modify the request URL. See [@fastify/http-proxy](https://github.com/fastify/fastify-http-proxy?tab=readme-ov-file#prerewrite).
      - **`preValidation`** (`function`) - A function that runs before proxying. Can be either:
        - An async function: `(request, reply) => Promise<boolean>` - Return `false` to stop the request proxying and return an error. Return `true` or `undefined` to continue.
        - A callback function: `(request, reply, done) => void` - Call `done()` to continue or `done(error)` to stop with an error.
          See [fastify preValidation hook](https://fastify.dev/docs/latest/Reference/Hooks/#prevalidation) for further information.
      - **`getUpstream`** (`function`) - A function `(request, base) => string` that dynamically determines the upstream URL for each request. Receives the request object and the base upstream URL. Note: `request.body` is a readable stream by default. If you need to access the body content as JSON or string in `getUpstream`, use `preValidation` to parse the body first. See [@fastify/fastify-reply-from](https://github.com/fastify/fastify-reply-from?tab=readme-ov-file#getupstreamrequest-base) for further information.

        When `getUpstream` is provided, the following guarantees apply:

        - The `upstream` setting is ignored and `base` may be `undefined`, so the function must always return a full origin (for example `http://127.0.0.1:3042` or `http://my-application.plt.local`).
        - When running inside Platformatic Runtime or Watt, the returned origin can be the internal mesh address `http://<application-id>.plt.local` of **any** application in the runtime, including applications which are **not** listed in the gateway `applications` configuration. Such requests are routed through the runtime mesh network. This makes it possible to keep a single logical entry in the gateway configuration and dispatch each request to one of several runtime applications (for example several versions of the same application) at runtime.
        - When no `ws.upstream` is configured, `getUpstream` also selects the upstream for WebSocket connections. It is invoked once per connection with the upgrade request at upgrade time.
      - **`rewriteHeaders`** (`function`) - A function `(headers, request) => headers` invoked with the response headers received from the upstream (after the gateway performed its internal `Location` header rewriting) and the original request. It must return the headers object to send back to the client. Use it, for example, to add a `Set-Cookie` header which pins a client to the upstream selected by `getUpstream`. Since both hooks receive the same request object, `getUpstream` can attach data to it (e.g. `request.selectedUpstream = ...`) and `rewriteHeaders` can read it back.
      - **`onError`** (`function`) - A function `(reply, { error }) => void` invoked when proxying a request fails. The gateway first logs the error, then invokes this hook instead of its default handler (which forwards the error to the client). Use `reply` to send a custom response. See [@fastify/fastify-reply-from](https://github.com/fastify/fastify-reply-from?tab=readme-ov-file#onerrorreply-error) for further information.

    :::note
    If the prefix is not explicitly set, the gateway and the application will try to find the best prefix for the application.

    First of all, if the application code used the `platformatic.setBasePath` (which is always available in each application),
    then the value will become the application prefix.

    The next attempt will be to let the application autodetect its own prefix by using the configuration (as the `basePath` setting for `@platformatic/service`)
    or by autodetecting the prefix from the host application (like Next.js).

    When none of the criteria above successfully lead to a prefix, the application ID is chosen as last fallback to ensure there are not routing conflicts.
    :::

    **Example: Basic HTTP Proxy**

    ```json
    {
      "id": "external-api",
      "proxy": {
        "prefix": "/api",
        "upstream": "https://api.example.com"
      }
    }
    ```

    **Example: Method/Route-based Proxy Selection**

    ```json
    {
      "id": "public-read-api",
      "proxy": {
        "prefix": "/",
        "methods": ["GET"],
        "routes": ["/public/*"]
      }
    }
    ```

    **Example: WebSocket Proxy with Reconnection**

    ```json
    {
      "id": "ws-service",
      "proxy": {
        "prefix": "/ws",
        "upstream": "http://localhost:3000",
        "ws": {
          "upstream": "ws://localhost:3000",
          "reconnect": {
            "pingInterval": 5000,
            "maxReconnectionRetries": 10,
            "reconnectInterval": 1000,
            "reconnectDecay": 1.5,
            "connectionTimeout": 5000,
            "reconnectOnClose": true,
            "logs": true
          }
        }
      }
    }
    ```

    **Example: Custom Proxy Logic**

    ```json
    {
      "id": "dynamic-router",
      "proxy": {
        "prefix": "/",
        "custom": {
          "path": "./custom-proxy.js"
        }
      }
    }
    ```

    Where `custom-proxy.js` exports:

    ```javascript
    export default {
      preRewrite: url => {
        return url.replace(/^\/admin/, '')
      },
      preValidation: async (request, reply) => {
        // Validate request before proxying
        if (!request.headers['authorization']) {
          reply.code(401).send({ error: 'Unauthorized' })
          return false
        }
        return true
      },
      getUpstream: (request, base) => {
        // Route to different upstreams based on request
        if (request.url.startsWith('/v2')) {
          return 'http://api-v2.example.com'
        }
        return 'http://api-v1.example.com'
      }
    }
    ```

    **Example: Per-Request Version Routing (header or cookie based)**

    A single logical application is listed in the gateway configuration, while the requests
    are dispatched at runtime to several applications running in the same runtime
    (for example several versions of the same application). The target applications
    do not need to be listed in the gateway configuration: any `http://<application-id>.plt.local`
    origin is routed through the runtime mesh network.

    ```json
    {
      "id": "main",
      "proxy": {
        "prefix": "/",
        "custom": {
          "path": "./version-router.js",
          "options": {
            "header": "x-app-version",
            "cookie": "app-version",
            "fallback": "main"
          }
        }
      }
    }
    ```

    Where `version-router.js` exports a factory function receiving `custom.options`:

    ```javascript
    function parseCookies (header) {
      const cookies = {}

      for (const part of (header ?? '').split(';')) {
        const index = part.indexOf('=')

        if (index !== -1) {
          cookies[part.slice(0, index).trim()] = decodeURIComponent(part.slice(index + 1).trim())
        }
      }

      return cookies
    }

    export default function createVersionRouter (options) {
      return {
        getUpstream (request) {
          // Select the version via a request header or a cookie
          const version =
            request.headers[options.header] ?? parseCookies(request.headers.cookie)[options.cookie]

          if (version) {
            request.selectedVersion = version
            return `http://${version}.plt.local`
          }

          return `http://${options.fallback}.plt.local`
        },
        rewriteHeaders (headers, request) {
          // Pin the client to the selected version on subsequent requests
          if (request.selectedVersion) {
            headers['set-cookie'] = `${options.cookie}=${request.selectedVersion}; Path=/`
          }

          return headers
        },
        onError (reply, { error }) {
          reply.code(503).send({ error: 'Selected version is unavailable' })
        }
      }
    }
    ```

    **Example: Hostname-based Routing**

    ```json
    {
      "id": "multi-tenant",
      "proxy": {
        "hostname": "tenant1.example.com",
        "upstream": "http://tenant1-service"
      }
    }
    ```

- **`openapi`** (`object`) - See the Platformatic Service [openapi](../service/configuration.md#service) option for more details.
- **`graphql`** (`object`) - Has the Platformatic Service [graphql](../service//configuration.md#service) options, plus
  - **`addEntitiesResolvers`** (`boolean`) - Automatically add related entities on GraphQL types, following the applications entities configuration. See [graphql-composer entities](https://github.com/platformatic/graphql-composer#gateway-entities) for details.
  - **`defaultArgsAdapter`** (`function` or `string`) - The default `argsAdapter` function for the entities, for example for the `@platformatic/db` mapped entities queries.

  ```js
  graphql: {
    defaultArgsAdapter: partialResults => ({ where: { id: { in: partialResults.map(r => r.id) } } })
  }
  ```

  or with the [metaline](https://github.com/platformatic/metaline) syntax, especially in the case of using the json configuration.

  ```json
  "defaultArgsAdapter": "where.id.in.$>#id"
  ```

  - **`onSubgraphError`** (`function`) - Hook called when an error occurs getting schema from a subgraph. The arguments are:
    - `error` (`error`) - The error message
    - `subgraphName` (`string`) - The erroring subgraph

    It's important to note GraphQL subscriptions are not supported in the gateway yet.

- **`refreshTimeout`** (`number`) - The number of milliseconds to wait for check for changes in the applications. If not specified, the default value is `1000`; set to `0` to disable. This is only supported if the Gateway is running within a [Platformatic Runtime](../runtime/overview.md).

- **`addEmptySchema`** (`boolean`) - Deprecated, it no longer has any effect. Responses which declare no body - a `204`, a `304`, or any other status code whose response object has no `content` - always keep their status code in the composed OpenAPI specification, and are documented without a body.

- **`handler`** (`string`) - Path to a JavaScript or TypeScript module that exports a custom proxy handler, either as `handler` or as the default export. The handler receives `(request, reply, dest, options)`, where `dest` is the rewritten proxy destination and `options` are the reply options passed to `reply.from()`. By default, proxied requests call `reply.from(dest, options)`; use this option to customize that behavior.

  ```js title="handler.js"
  export function handler (request, reply, dest, options) {
    if (request.headers['x-custom-response'] === 'true') {
      return reply.send({ dest })
    }

    return reply.from(dest, options)
  }
  ```

  ```json title="Example JSON object"
  {
    "gateway": {
      "handler": "./handler.js",
      "applications": [
        {
          "id": "api",
          "proxy": {
            "prefix": "/api",
            "upstream": "http://localhost:3000"
          }
        }
      ]
    }
  }
  ```

- **`deduplication`** (`object`) - Deduplicates concurrent proxied requests with the same computed key. The first request is sent upstream, while matching concurrent requests wait for the first response and replay it. This can be configured globally under `gateway.deduplication` or per application under `gateway.applications[].proxy.deduplication`. Application-level settings override global settings. If both `handler` and `deduplication` are configured, deduplication runs first and the winning request is delegated to the custom handler. See [Request Deduplication](./deduplication.md) for usage examples.

  Supported options:

  - **`enabled`** (`boolean` or `string`) - Enables deduplication. Default: `false`.
  - **`storage`** (`object`) - Storage backend configuration.

    Supported sub-options:

    - **`adapter`** (`string`, default: `memory`) - Selects the storage backend. Storage keeps in-flight locks and replayable responses: use `memory` within one gateway instance, or `valkey` to coordinate across gateway workers, instances, or pods through a Redis-compatible Valkey server.
    - **`url`** (`string`, required when `adapter` is `valkey`) - Redis-compatible Valkey connection URL. Example: `redis://127.0.0.1:6379`.
    - **`prefix`** (`string`, optional, only used when `adapter` is `valkey`) - Prefix prepended to every gateway deduplication key stored in Valkey. Use this when multiple applications share the same Valkey instance.

    Examples:

    ```json
    {
      "adapter": "memory"
    }
    ```

    ```json
    {
      "adapter": "valkey",
      "url": "redis://127.0.0.1:6379",
      "prefix": "my-app"
    }
    ```

  - **`methods`** (`array of string`, default: `['GET', 'HEAD']`) - Methods eligible for deduplication when `routes` is not specified.
  - **`headers`** (`array of string`, default: `['authorization', 'accept', 'accept-encoding', 'accept-language']`) - Request headers included in the default deduplication key.
  - **`skipHeaders`** (`array of string`, default: `['cookie']`) - Request headers whose presence bypasses deduplication entirely. These headers are evaluated independently from the headers used to construct the key. Real-browser cookies are per user, so cookie-bearing requests skip the deduplication overhead by default.
  - **`routes`** (`array`) - Optional route whitelist. When specified, routes decide whether deduplication applies instead of `methods` alone. Routes use `find-my-way` syntax and accept either `method` or `methods` plus `path`.
  - **`key`** (`string`) - Path to a JavaScript or TypeScript module exporting a synchronous `computeDeduplicationKey(request, context)` function to customize key computation.
  - **`timeout`** (`number`, default: `1000`) - Milliseconds a duplicate request waits for the leader response before retrying lock acquisition.
  - **`retries`** (`number`, default: `3`) - Number of additional deduplication attempts before falling back to a normal proxied request.
  - **`ttl`** (`number`, default: `10000`) - Milliseconds stored responses remain available for waiting requests.
  - **`lockTtl`** (`number`, default: `500`) - Milliseconds before an in-flight lock expires.

  Default key computation uses the configured application `origin`, request method, rewritten proxy URL including query string, and the configured request headers.

  ```json
  {
    "gateway": {
      "deduplication": {
        "enabled": true,
        "storage": {
          "adapter": "valkey",
          "url": "redis://127.0.0.1:6379",
          "prefix": "my-app"
        },
        "routes": [
          { "method": "GET", "path": "/blog/*" }
        ]
      }
    }
  }
  ```

  A custom key module receives the request and the default key context. The function must be synchronous:

  ```js
  export function computeDeduplicationKey (request, context) {
    return `${context.origin}:${context.method}:${context.url}`
  }
  ```

  Custom gateway handlers that override `onResponse` or `onError` can call `options.deduplicateResponse(request, reply, res)` and `options.deduplicateError(reply, error)` to keep duplicate requests coordinated. See [Request Deduplication](./deduplication.md#custom-gateway-handlers) for examples.

- **`passthroughContentTypes`** (`array`) - An array of content types that should be passed through without parsing to enable proxying. This is useful for handling multipart forms, binary data, or other content types that need to be forwarded to backend services without modification. Default is `['multipart/form-data', 'application/octet-stream']`.

  ```json title="Example JSON object"
  {
    "gateway": {
      "passthroughContentTypes": ["multipart/form-data", "application/octet-stream", "application/custom-binary"]
    }
  }
  ```

### OpenAPI

- **`url`** (`string`) - A path of the route that exposes the OpenAPI specification. If an application is a Platformatic Service or Platformatic DB, use `/documentation/json` as a value. Use this or `file` option to specify the OpenAPI specification.
- **`file`** (`string`) - A path to the OpenAPI specification file. Use this or `url` option to specify the OpenAPI specification.
- **`prefix`** (`string`) - A prefix for the OpenAPI specification. All application routes will be prefixed with this value.
- **`config`** (`string`) - A path to the OpenAPI configuration file. This file is used to customize the [OpenAPI](#openapi-configuration)specification.

### OpenAPI Configuration

The OpenAPI configuration file is a JSON file that is used to customize the OpenAPI specification. It supports the following options:

- **`ignore`** (`boolean`) - If `true`, the route will be ignored by the gateway.
  If you want to ignore a specific method, use the `ignore` option in the nested method object.

  ```json title="Example JSON object"
  {
    "paths": {
      "/users": {
        "ignore": true
      },
      "/users/{id}": {
        "get": { "ignore": true },
        "put": { "ignore": true }
      }
    }
  }
  ```

- **alias** (`string`) - Use it create an alias for the route path. Original route path will be ignored.

  ```json title="Example JSON object"
  {
    "paths": {
      "/users": {
        "alias": "/customers"
      }
    }
  }
  ```

- **`rename`** (`string`) - Use it to rename composed route response fields.
  Use json schema format to describe the response structure, this only for `200` response.

  ```json title="Example JSON object"
  {
    "paths": {
      "/users": {
        "responses": {
          "200": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": { "rename": "user_id" },
                "name": { "rename": "first_name" }
              }
            }
          }
        }
      }
    }
  }
  ```

  Composition of two remote applications:

  ```json title="Example JSON object"
  {
    "gateway": {
      "applications": [
        {
          "id": "auth-service",
          "origin": "https://auth-service.com",
          "openapi": {
            "url": "/documentation/json",
            "prefix": "auth"
          }
        },
        {
          "id": "payment-service",
          "origin": "https://payment-service.com",
          "openapi": {
            "file": "./schemas/payment-service.json"
          }
        }
      ],
      "refreshTimeout": 1000
    }
  }
  ```

  Composition of two local applications inside Platformatic Runtime:

  ```json title="Example JSON object"
  {
    "gateway": {
      "applications": [
        {
          "id": "auth-service",
          "openapi": {
            "url": "/documentation/json",
            "prefix": "auth"
          }
        },
        {
          "id": "payment-service",
          "openapi": {
            "file": "./schemas/payment-service.json"
          }
        }
      ],
      "refreshTimeout": 1000
    }
  }
  ```

### GraphQL

- **`host`** (`string`) - application host; if not specified, the `application.origin` is used.
- **`name`** (`string`) - name to identify the application. If not specified, the `application.origin` is used.
- **`graphqlEndpoint`** (`string`) - The graphql endpoint path, the default value is the common `'/graphql'`.
- **`composeEndpoint`** (`string`) - The endpoint to retrieve the introspection query from, default is `'/.well-known/graphql-composition'`. In case the endpoint is not available, a second call with introspection query will be sent to the `graphqlEndpoint`.
- **`entities`** (`object`) - Configuration object for working with entities in this subgraph, the values are objects with the following schema:
  - **`resolver`** (`object`) - The resolver to retrieve a list of objects - should return a list - and should accept as an arguments a list of primary keys or foreign keys.
    - **`name`** (`string`, **required**) - The name of the resolver.
    - **`argsAdapter (partialResults)`** (`function` or `string`) - The function invoked with a subset of the result of the initial query, where `partialResults` is an array of the parent node. It should return an object to be used as argument for `resolver` query. Can be a function or a [metaline](https://github.com/platformatic/metaline) string.
      **Default:** if missing, the `defaultArgsAdapter` function will be used; if that is missing too, a [generic one](https://github.com/platformatic/graphql-composer/blob/main/lib/utils.js) will be used.
    - **`partialResults`** (`function` or `string`) - The function to adapt the subset of the result to be passed to `argsAdapter` - usually is needed only on resolvers of `fkeys` and `many`. Can be a function or a [metaline](https://github.com/platformatic/metaline) string.
  - **`pkey`** (`string`, **required**) - The primary key field to identify the entity.
  - **`fkeys`** (`array of objects`) an array to describe the foreign keys of the entities, for example `fkeys: [{ type: 'Author', field: 'authorId' }]`.
    - **`type`** (`string`, **required**) - The entity type the foreign key is referred to.
    - **`field`** (`string`) - The foreign key field.
    - **`as`** (`string`) - When using `addEntitiesResolvers`, it defines the name of the foreign entity as a field of the current one, as a single type.
    - **`pkey`** (`string`) - The primary key of the foreign entity.
    - **`subgraph`** (`string`) - The subgraph name of the foreign entity, where the resolver is located; if missing is intended the self.
    - **`resolver`** (object) - The resolver definition to query the foreign entity, same structure as `entity.resolver`.
  - **`many`** (`array of objects`) - Describe a 1-to-many relation - the reverse of the foreign key.
    - **`type`** (`string`, **required**) - The entity type where the entity is a foreign key.
    - **`fkey`** (`string`, **required**) - The foreign key field in the referred entity.
    - **`as`** (`string`, **required**) - When using `addEntitiesResolvers`, it defines the name of the relation as a field of the current one, as a list.
    - **`pkey`** (`string`) - The primary key of the referred entity.
    - **`subgraph`** (`string`) - The subgraph name of the referred entity, where the resolver is located; if missing is intended the self.
    - **`resolver`** (`object`, **required**) - The resolver definition to query the referred entity, same structure as `entity.resolver`.

## Configuration References

### `telemetry`

Telemetry involves the collection and analysis of data generated by the operations of applications. See our [telemetry documentation](../service/configuration.md#telemetry) for details on configuring telemetry for Platformatic Service.

### `watch`

The `watch` functionality helps in monitoring file changes and dynamically updating applications. Learn more at Platformatic Service [watch](../service/configuration.md#watch)

## Setting and Using ENV placeholders

Environment variable placeholders are used to securely inject runtime configurations. Learn how to [set](../service/configuration.md#setting-environment-variables) and [use](../service/configuration.md#environment-variable-placeholders) environment variable placeholders [documentation](../service/configuration.md).

### PLT_ROOT

The [PLT_ROOT](../service/configuration.md#plt_root) variable is used to configure relative path and is set to the directory containing the Service configuration file.

<Issues />
