Run multiple instances of a Kong Gateway plugin

Deployment Platform
Related Resources
Minimum Version
Kong Gateway - 3.15
TL;DR

To apply a plugin multiple times with different configurations, clone the plugin using the cloned_plugins key, then configure the clone the same as any other plugin through plugins.

Prerequisites

This is a Konnect tutorial and requires a Konnect personal access token.

  1. Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.

  2. Export your token to an environment variable:

    export KONNECT_TOKEN='YOUR_KONNECT_PAT'
  3. Run the quickstart script to automatically provision a Control Plane and Data Plane, and configure your environment:

    curl -Ls https://get.konghq.com/quickstart | bash -s -- -k $KONNECT_TOKEN \
         --deck-output

    This sets up a Konnect Control Plane named quickstart, provisions a local Data Plane, and prints out the following environment variable exports:

    export DECK_KONNECT_TOKEN=$KONNECT_TOKEN
    export DECK_KONNECT_CONTROL_PLANE_NAME=quickstart
    export KONNECT_CONTROL_PLANE_URL=https://us.api.konghq.com
    export KONNECT_PROXY_URL='http://localhost:8000'

    Copy and paste these into your terminal to configure your session.

This tutorial requires Kong Gateway Enterprise. If you don’t have Kong Gateway set up yet, you can use the quickstart script with an enterprise license to get an instance of Kong Gateway running almost instantly.

  1. Export your license to an environment variable:

     export KONG_LICENSE_DATA='LICENSE-CONTENTS-GO-HERE'
  2. Run the quickstart script:

    curl -Ls https://get.konghq.com/quickstart | bash -s -- -e KONG_LICENSE_DATA 

    Once Kong Gateway is ready, you will see the following message:

     Kong Gateway Ready

To complete this tutorial, install decK. We recommend keeping decK up to date with the latest version (1.64.0).

decK is a CLI tool for managing Kong Gateway declaratively with state files. This guide uses deck gateway apply, which directly applies entity configuration to your Gateway instance.

You can check your current decK version with deck version.

For this tutorial, you’ll need Kong Gateway entities, like Gateway Services and Routes, pre-configured. These entities are essential for Kong Gateway to function but installing them isn’t the focus of this guide. Follow these steps to pre-configure them:

  1. Run the following command:

    echo '
    _format_version: "3.0"
    services:
      - name: example-service
        url: http://httpbin.konghq.com/anything
    routes:
      - name: example-route
        paths:
        - "/anything"
        service:
          name: example-service
        protocols:
        - http
        - https
    ' | deck gateway apply -

To learn more about entities, you can read our entities documentation.

If you’re not using the Gateway quickstart, make sure your Gateway user has super-admin or admin permissions (not workspace-super-admin or workspace-admin.) The quickstart demo user has these permissions by default.

Ensure your Konnect account has one of the following control plane roles: ServiceAdmin, RouteAdmin, PluginAdmin, CPAdmin, or Deployer.

In this guide, you’ll clone the Request Transformer plugin to run two independent instances with different configurations:

  • A global clone that adds a header to every request passing through the gateway.
  • The original plugin applied to a specific Route that adds a different header.

This lets two separate teams use the same plugin logic with independent configuration and precedence.

Create a clone of the Request Transformer plugin

Use the cloned_plugins key to define a new plugin named acme-request-transformer-global that is based on request-transformer:

echo '
_format_version: "3.0"
cloned_plugins:
  - name: acme-request-transformer-global
    ref: request-transformer
    priority: 802
' | deck gateway apply --include-plugin-definitions -

Where:

  • cloned_plugins.name: A unique name for the clone. This can be any name that doesn’t conflict with an existing plugin. We recommend making this name distinct so that it doesn’t conflict with future plugins (for example, acme-request-transformer-global).
  • cloned_plugins.ref: The source plugin that this clone is based on.
  • cloned_plugins.priority: The order in which the cloned plugin runs relative to other plugins. The base Request Transformer plugin has a priority of 801, so setting 802 makes the clone run first. This isn’t required for this example since the clone runs globally, but it shows how you can control plugin ordering independently from the source plugin.

Apply the cloned plugin globally

Configure the cloned plugin globally so it adds a header to every request:

echo '
_format_version: "3.0"
plugins:
  - name: acme-request-transformer-global
    config:
      add:
        headers:
        - X-Global-Header:isSetGlobally
' | deck gateway apply --include-plugin-definitions -

Apply the source plugin to a Route

Configure the original Request Transformer plugin on example-route to add a Route-specific header. This runs as a separate, independent instance from the global clone:

echo '
_format_version: "3.0"
plugins:
  - name: request-transformer
    route: example-route
    config:
      add:
        headers:
        - X-Route-Header:isSetOnRoute
' | deck gateway apply -

Create a second route

Create a second Route on example-service to use in validation. Requests to this Route will only be handled by the global clone, not the route-scoped plugin:

echo '
_format_version: "3.0"
routes:
  - name: example-route-2
    service:
      name: example-service
    paths:
    - "/global"
    protocols:
    - http
    - https
' | deck gateway apply -

Validate

First, send a request to example-route, which triggers both plugins. The global clone adds X-Global-Header and the route-scoped plugin adds X-Route-Header:

curl -i "$KONNECT_PROXY_URL/anything" \
     --no-progress-meter --fail-with-body 
curl -i "http://localhost:8000/anything" \
     --no-progress-meter --fail-with-body 

In the response from httpbin, look for both headers in the headers object:

{
  "headers": {
    "X-Global-Header": "isSetGlobally",
    "X-Route-Header": "isSetOnRoute"
  }
}

Now send a request to example-route-2:

curl -i "$KONNECT_PROXY_URL/global" \
     --no-progress-meter --fail-with-body 
curl -i "http://localhost:8000/global" \
     --no-progress-meter --fail-with-body 

Only the global clone should run, so you should only see X-Global-Header:

{
  "headers": {
    "X-Global-Header": "isSetGlobally"
  }
}

The global clone runs on both Routes, while request-transformer only runs on example-route, confirming that the two instances are fully independent.

Cleanup

If you created a new control plane and want to conserve your free trial credits or avoid unnecessary charges, delete the new control plane used in this tutorial.

curl -Ls https://get.konghq.com/quickstart | bash -s -- -d

FAQs

No, only a subset of plugins can be cloned. See the list of supported plugins.

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!