<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Shubhojit Dasgupta on Medium]]></title>
        <description><![CDATA[Stories by Shubhojit Dasgupta on Medium]]></description>
        <link>https://medium.com/@shubhojit.dasgupta?source=rss-88db77259f8a------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*W0aiZ0-V9FDYt8d3Y7owaw.jpeg</url>
            <title>Stories by Shubhojit Dasgupta on Medium</title>
            <link>https://medium.com/@shubhojit.dasgupta?source=rss-88db77259f8a------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 22 May 2026 18:19:41 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@shubhojit.dasgupta/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port…]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-83a4cef197ee?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/83a4cef197ee</guid>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[bash]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[kong-konnect]]></category>
            <category><![CDATA[api-gateway]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Mon, 11 May 2026 12:47:25 GMT</pubDate>
            <atom:updated>2026-05-11T12:47:25.642Z</atom:updated>
            <cc:license>https://creativecommons.org/licenses/by-nc-nd/4.0/</cc:license>
            <content:encoded><![CDATA[<h3>Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port Number — Part-4</h3><figure><img alt="Technical banner illustration showing a Kong Konnect-managed Kong Gateway Enterprise Data Plane filtering inbound API requests by destination port number using Kong Expressions Routing." src="https://cdn-images-1.medium.com/max/1024/1*WVsdSOc4qxkak5mH8hd0og.png" /><figcaption>Kong Konnect-managed Kong Gateway Enterprise, filtering inbound API requests by destination port number</figcaption></figure><p>Shubhojit Dasgupta — Independent API Architect</p><p><a href="https://medium.com/@shubhojit.dasgupta/611822f26fc2"><strong>Part-3</strong></a> of this blog series established the declarative onboarding workflow, for managing backend API services within the Kong Konnect Routing Control Plane using automation-driven configuration management. We onboarded the Kong Echo API and HTTPBin API backend services through automated Bash scripting and multiple decK reconciliation operations, converted the Echo API OpenAPI specification into Kong declarative configuration, and patched the generated configuration to automatically transform traditional routes while declaratively injecting the Request-Termination plugin for handling unnecessary browser /favicon.ico requests. Finally, we refreshed the backup.yaml declarative configuration state and validated zero-drift synchronization to confirm that the backup configuration remains the single source of truth for the live Routing Control Plane.</p><p>In the <strong>last part</strong> of this blog series, we will validate <strong>Expressions-based routing policies</strong> in Kong Gateway, to <strong>filter inbound API</strong> requests by <strong>destination port number</strong>, <strong>verify request flow</strong> behavior across multiple Gateway listener ports, and analyze how Kong Expressions Routing improves route matching flexibility and operational control within the Kong Konnect-managed <strong>self-managed Gateway</strong> environment. Additionally, we will implement an automated backup and controlled reconciliation workflow to safely synchronize the Kong Konnect Routing Control Plane with the local backup.yaml declarative configuration state, ensuring that the declarative configuration remains the <strong>single source of truth</strong> for the live Routing Control Plane.</p><h3>Validating API Requests to echo API Backend Service</h3><figure><img alt="Browser sends an API request to echo Backend Service on /echo endpoint to Kong Gateway on 443 port. The API request gets proxied via Kong to the echo API backend service sending the response back to the browser with 200 OK response status code." src="https://cdn-images-1.medium.com/max/1024/1*6XebQK1nkG9JVyw0nJs-IQ.png" /><figcaption>API request <strong>/echo</strong> sent from browser to <strong>echo API</strong> backend service on <strong>port 443</strong> with successful <strong>200 OK</strong> response status code <strong>via Kong Gateway</strong></figcaption></figure><figure><img alt="Response Headers send from echo API Backend Upstream Service to the Browser client via Kong Gateway. The Via header in the response verify that the request was proxied via the Kong Gateway and back to the client Browser." src="https://cdn-images-1.medium.com/max/1024/1*YddyP0o2I7k2LPjbuCsRhQ.png" /><figcaption><strong>Response Headers</strong> send from <strong>echo API</strong> Backend Upstream Service to the Browser client <strong>via Kong Gateway</strong></figcaption></figure><p>The response headers depict a successful browser request sent to <a href="https://localhost/echo"><em>https://localhost/echo</em></a> on Kong Gateway port 443. The browser issues an HTTP <em>GET</em> request to the <em>/echo</em> path, and because the request matches the Expressions route configured with <em>http.method</em> <em>==</em> <em>“GET”</em>, <em>http.path</em> <em>^=</em> <em>“/echo”</em>, and <em>net.dst.port</em> <em>==</em> <em>443</em>, Kong Gateway <strong>forwards</strong> the API traffic successfully to the local Kong echo API backend service. A <em>GET</em> request from the Browser does not carry a request body, so the upstream echo service responds only with an HTTP <em>200 OK</em> status and no message payload in the response body. The response headers visible in the browser confirm that the request was processed through Kong Gateway. In particular, the <em>Server</em> and <em>Via</em> headers expose the Kong Gateway <strong>version</strong> that proxied the request to the <strong>echo API</strong> backend and relayed the successful response back to the browser client.</p><figure><img alt="Unnecessary Browser request to /favicon.ico terminated by request-termination plugin on echo-api-favicon route and response 204 No Content sent to browser by the plugin directly through the Kong Gateway. The request is not forwarded to the actual echo API backend service." src="https://cdn-images-1.medium.com/max/1024/1*HuQXDni8IkaTzVvChJPy7Q.png" /><figcaption><strong>Browser</strong> request to<strong> /favicon.ico</strong> served directly by Kong Gateway</figcaption></figure><p>An automatic browser request to <em>/favicon.ico</em> is intercepted and handled directly by Kong Gateway instead of being forwarded to the upstream <strong>echo API</strong> backend service. When the browser requests the page on port <em>443</em>, it also issues a background <em>GET</em> request for the<em>/favicon.ico</em> endpoint of <em>echo-api-</em><em>service</em>. That request matches the <em>echo-api-favicon</em> Expressions route because the path begins with <em>/favicon.ico</em>, the method is <em>GET</em>, and the destination port is <em>443</em>. Instead of proxying this unnecessary browser-generated request to the echo API backend, the attached <em>request-termination</em> plugin responds immediately at the Kong Gateway layer with an HTTP 204 No Content response. This avoids needless upstream traffic, keeps the echo service focused on real API calls, and demonstrates how Kong Gateway can efficiently absorb non-business browser requests without involving the backend service.</p><figure><img alt="A GET API request to https://localhost:8443/echo returning 404 Not Found because the echo API route is configured to match only on Kong Gateway port 443, not 8443." src="https://cdn-images-1.medium.com/max/1024/1*69pq0fsm9efAzhb-oLiqJg.png" /><figcaption>Browser API request to <strong>/echo</strong> on port <strong>8443 </strong>rejected by Kong Gateway with <strong>404 Not Found</strong></figcaption></figure><p>A browser request to <a href="https://localhost:8443/echo"><em>https://localhost:8443/echo</em></a> returns <em>404</em> <em>Not</em> <em>Found</em> because the <strong>Kong</strong> echo API backend service route is intentionally restricted to Kong Gateway port 443. Although the request path begins with <em>/echo</em> and the method is <em>GET</em>, the route expression also requires net.dst.port == 443. Since this request arrives on port <em>8443</em>, the full expression evaluates to <strong>false</strong>, no Kong Route is matched, and Kong Gateway returns a <em>404</em> <em>Not</em> <em>Found</em> response immediately. This confirms that traffic filtering is being enforced not only by path and method, but also by destination port, and that requests sent to the wrong Gateway port are rejected before they ever reach the upstream echo API backend service.</p><figure><img alt="Browser request to /favicon.ico on Kong Gateway port 8443 is matched by example-favicon-route and intercepted by the request-termination plugin instead of being forwarded to the HTTPBin upstream service." src="https://cdn-images-1.medium.com/max/1024/1*eiyCPzGSmgvqRJAk54pdSQ.png" /><figcaption>Browser Request to <strong>/favicon.ico</strong> to Kong Gateway on <strong>8443 Port</strong> is intercepted by <strong>Request-Termination</strong> Plugin on <strong>example-favicon-route</strong></figcaption></figure><p>An automatic browser request to <em>/favicon.ico</em> on Kong Gateway port <em>8443</em> is intercepted by the <em>example-favicon-route </em>instead of being forwarded to the HTTPBin upstream service. The Expressions route matches because the request path begins with<em>/favicon.ico</em> and the destination port satisfies <em>net.dst.port</em> <em>==</em> <em>8443</em>. Once matched, the attached <em>request-termination </em>plugin responds directly at the Kong Gateway layer with the configured response, preventing an unnecessary call to the upstream HTTPBin API. This keeps background browser noise out of the backend service, reduces needless proxy traffic, and confirms that even non-business requests on port <em>8443</em> can be cleanly handled at the Gateway itself.</p><figure><img alt="HTTP 200 response returned by Kong Gateway for a browser request to /favicon.ico on port 8443, with the request-termination plugin echoing request details instead of forwarding the call to the HTTPBin upstream service." src="https://cdn-images-1.medium.com/max/1024/1*o6zbJWvIawfFlRWdJqMLTQ.png" /><figcaption><strong>Request-Termination</strong> Plugin sending the configured <strong>message</strong> and status code back to Browser in the Response</figcaption></figure><p>The browser request to <em>/favicon.ico</em> on Kong Gateway port <em>8443</em> is matched by <em>example-favicon-route</em>, which is intentionally dedicated to absorbing this non-business browser traffic before it reaches the HTTPBin upstream service. Once the route expression evaluates successfully, the attached <em>request-termination</em> plugin returns the configured <em>200</em> response directly from Kong Gateway along with the <em>echoed</em> request details, because the plugin is configured with <em>echo:</em> <em>true</em>. This confirms that <em>favicon</em> requests are handled entirely at the Kong Gateway layer, reducing unnecessary backend calls while still giving a clear visible response in the browser.</p><h3>Validating API Requests to HTTPBin API Backend Service</h3><figure><img alt="Browser sending an API GET request to the HTTPBin API /anything endpoint through https://localhost:8443, demonstrating that Kong Gateway forwards traffic successfully on port 8443 to the HTTPBin upstream service. The HTTPBin upstream service at /anything route path echoes back the browser’s request with request headers as a Response to the Browser client with 200 OK response status." src="https://cdn-images-1.medium.com/max/1024/1*nr3v7Xc2ba3r1VSBHrtzDQ.png" /><figcaption>Browser Sending Request to <strong>/anything</strong> endpoint of <strong>HttpBin API</strong> via Kong Gateway on <strong>8443 Port</strong></figcaption></figure><p>A browser request sent to <a href="https://localhost:8443/anything"><em>https://localhost:8443/anything</em></a> is successfully matched by the <em>example-status-route</em> because the request path begins with <em>/anything</em> and the destination port satisfies <em>net.dst.port</em> <em>==</em> <em>8443</em>. Once the expression evaluates to true, Kong Gateway forwards the request to the <strong>HTTPBin</strong> <strong>upstream service</strong> configured under <em>example-service</em>. The <em>/anything</em> endpoint is designed to <em>echo</em> request details back to the client, so the browser receives an HTTP <em>200 OK</em> response containing headers and other request metadata returned by <strong>HTTPBin</strong> through Kong Gateway. At the same time, any automatic browser request to <em>/favicon.ico</em> on port <em>8443</em> is matched by <em>example-favicon-route</em> and handled entirely inside Kong Gateway by the attached <em>request-termination</em> plugin, which returns the configured <em>200 OK</em> response directly from the gateway without forwarding that background browser request to the HTTPBin API backend service.</p><figure><img alt="Browser sending an API GET request to https://localhost:8443/status/200 routed through Kong Gateway and forwarded successfully to the HTTPBin API upstream, which returns an HTTP 200 OK response on the port 8443 Expressions route." src="https://cdn-images-1.medium.com/max/1024/1*u6ad8o8QiVIV7lriGd2RTA.png" /><figcaption>Browser Sending Request to <strong>/status/200</strong> endpoint of <strong>HttpBin API</strong> via Kong Gateway on <strong>8443 Port</strong></figcaption></figure><p>A browser request to <a href="https://localhost:8443/status/200"><em>https://localhost:8443/status/200</em></a> is successfully matched by <em>example-status-route</em> because the request path satisfies the regular expression for the <em>/status/&lt;status_code&gt;</em> endpoint and the destination port matches <em>8443</em>. Kong Gateway therefore forwards the request to the <strong>HTTPBin</strong> <strong>upstream service</strong>, which responds with the expected HTTP <em>200 OK</em> status and sends that successful response back to the browser through the Gateway. At the same time, the browser also issues its usual background request to <em>/favicon.ico</em> on the same port. That request <strong>does not</strong> reach <strong>HTTPBin</strong>, because it is matched separately by <em>example-favicon-route</em>, where the attached <em>request-termination</em> plugin handles it directly inside Kong Gateway and returns the configured response with the echoed message <em>“</em>Request terminated by plugin.<em>”</em>. This confirms that business API traffic is forwarded upstream as intended, while unnecessary browser-generated requests are absorbed and responded to within the Kong Gateway itself.</p><figure><img alt="Browser sending an API GET request to https://localhost/anything on port 443 rejected by Kong Gateway with 404 Not Found due to destination-port mismatch." src="https://cdn-images-1.medium.com/max/1024/1*1jS-KFoiwEMavimnISylNg.png" /><figcaption>Browser Sending Request to <strong>/anything</strong> endpoint of <strong>HttpBin API</strong> via Kong Gateway on <strong>443 Port</strong></figcaption></figure><p>A browser request to <a href="https://localhost/anything"><em>https://localhost/anything</em></a> returns <em>404</em> <em>Not</em> <em>Found</em> because the <strong>HTTPBin API</strong> route is intentionally restricted to Kong Gateway port <em>8443</em>. Although the request path begins with <em>/anything</em>, the Expressions route also requires <em>net.dst.port</em> <em>==</em> <em>8443</em>. Since this request arrives on port <em>443</em>, the full route expression evaluates to <strong>false</strong>, no Kong Route is matched, and Kong Gateway immediately returns a <em>404</em> <em>Not</em> <em>Found</em> response. This confirms that traffic for the <strong>HTTPBin API</strong> is filtered not only by path, but also by destination port, ensuring that requests sent to the wrong gateway listener are rejected before they ever reach the upstream HTTPBin service.</p><figure><img alt="Browser sending an API GET request to https://localhost/status/200 on port 443 rejected by Kong Gateway with 404 Not Found due to destination-port mismatch." src="https://cdn-images-1.medium.com/max/1024/1*_VJcYomGg-L3SyllG28tCA.png" /><figcaption>Browser Sending Request to <strong>/status/200</strong> endpoint of <strong>HttpBin API</strong> via Kong Gateway on <strong>443 Port</strong></figcaption></figure><p>A browser request to <a href="https://localhost/status/200"><em>https://localhost/status/200</em></a> returns <em>404</em> <em>Not</em> <em>Found</em> because the HTTPBin API route for the <em>/status/&lt;status_code&gt;</em> endpoint is intentionally restricted to Kong Gateway port <em>8443</em>. Although the request path matches the regular expression used by <em>example-status-route</em>, the Expressions route also requires <em>net.dst.port</em> <em>==</em> <em>8443</em>. Since this request arrives on port <em>443</em>, the full expression evaluates to <strong>false</strong>, no Kong Route is matched, and Kong Gateway immediately returns a <em>404</em> <em>Not</em> <em>Found</em> response. This confirms that the <strong>HTTPBin</strong> status endpoint is protected by the same port-aware routing policy, ensuring that requests sent to the wrong Kong Gateway listener port are rejected before they ever reach the upstream HTTPBin service.</p><figure><img alt="Browser sends a /favicon.ico request to Kong Gateway on port 443. The request matches echo-api-favicon and is immediately intercepted by the request-termination plugin, which returns an HTTP 204 No Content response directly to the browser instead of forwarding the request to the upstream Echo API service." src="https://cdn-images-1.medium.com/max/1024/1*RpyNVgJNd5pkA24ExNhGFg.png" /><figcaption>Browser Sending an unnecessary <strong>/favicon.ico</strong> request to Kong Gateway on <strong>443 Port</strong></figcaption></figure><p>A browser request to <em>/favicon.ico</em> on Kong Gateway port <em>443</em> is matched by the <em>echo-api-favicon</em> Expressions route, which is dedicated to handling this automatic browser traffic before it can reach the upstream Kong echo API service. Because the <em>route</em> is attached to the <em>request-termination</em> plugin, Kong Gateway immediately returns the configured 204 No Content response directly to the browser. This confirms that unnecessary <em>favicon</em> requests received on the Kong Gateway listener port <em>443</em> are absorbed entirely at the Gateway layer, reducing backend noise and ensuring that only meaningful API traffic is forwarded to the upstream service.</p><p>These validation steps confirm the core outcome of this implementation: <strong>Kong Gateway Expressions routing</strong> can reliably enforce API traffic segregation based on destination port while still evaluating request paths and methods. The Kong echo API is reachable only through port <em>443</em>, the HTTPBin API is reachable only through port <em>8443</em>, and requests sent to the wrong port are rejected with <em>404</em> <em>Not</em> <em>Found</em> before they ever reach the upstream service. At the same time, automatic browser requests to <em>/favicon.ico</em> are <em>intercepted</em> and <em>terminated</em> directly at the Kong Gateway layer, preventing unnecessary upstream calls for both services. Together, these results demonstrate a <em>clean</em>, <em>secure</em>, and <em>high-performance</em> approach to port-aware API traffic control in <strong>Kong Gateway</strong> using the <strong>Expressions</strong> router.</p><h3>Kong Konnect Routing Control Plane Backup</h3><p>Remember that while onboarding both the Kong echo API and the HTTPBin API into the Kong Konnect <em>Routing</em> Control Plane, a <em>backup.yaml</em> file was created in the <em>/scripts/sync</em> directory of the project. This <em>backup</em> file acts as the <strong>single source of truth</strong> for the current live state of the Routing Control Plane because it is generated directly from Kong Konnect using <em>deck gateway dump</em> after each successful <em>apply</em> operation. As a result, it captures the <strong>full Control Plane configuration</strong> in one place, including the self-signed certificate and <strong>SNI</strong> configured earlier through the Kong Konnect UI, the <em>echo-api</em> service with its <strong>Expressions-based routes</strong> and request-termination plugin, and the <em>example-service</em> for HTTPBin API with its combined Expressions routes and favicon-handling plugin. Because the file reflects the exact live runtime configuration, it becomes the most reliable artifact for validation, drift detection, auditability, and recovery. A subsequent <em>deck</em> <em>gateway</em> <em>diff </em>against <em>backup.yaml</em> should always report <strong>zero</strong> entities to <em>create</em>, <em>update</em>, or <em>delete</em> whenever the local backup remains aligned with the live Control Plane. In practice, this means the <em>backup.yaml</em> file should be preserved, version-controlled, and refreshed after every intentional configuration change so that the live Kong Konnect <em>Routing </em>Control Plane can always be reconstructed or verified from a single declarative artifact.</p><h4>Automated Bash Script to Synchronize Kong Konnect State with Backup</h4><p>Create a bash file <em>sync.sh</em> under the sync directory of the project. The bash script defined in <em>sync.sh</em> file detects any changes in the Kong Konnect <em>Routing</em> Control Plane Configuration by comparing the live Kong Konnect state with the local <em>backup.yaml</em>file and synchronizes the <em>Routing</em> Control Plane only when <strong>drift</strong> in Kong configuration is detected.</p><p><strong>File</strong> sync.sh:</p><pre>#! /usr/bin/env bash<br><br># Directory in which the deck sync script runs<br>cd kong/scripts/sync<br><br># Importing configuration variables<br>TOKEN_FILE=$(yq e &#39;.token_file&#39; ./config.yaml)<br>CONTROL_PLANE=$(yq e &#39;.control_plane&#39; ./config.yaml)<br>CONTROL_PLANE_ADDR=$(yq e &#39;.control_plane_addr&#39; ./config.yaml)<br><br># Backup file to sync (backup.yaml should be in this directory)<br>BACKUP_FILE=&quot;backup.yaml&quot;<br><br># Check if backup.yaml exists<br>if [ ! -f &quot;$BACKUP_FILE&quot; ]; then<br>    echo &quot;Error: $BACKUP_FILE not found in the sync directory&quot;<br>    exit 1<br>fi<br><br># Check for changes before synchronizing<br>echo &quot;Checking for changes in ${BACKUP_FILE}...&quot;<br>DIFF_OUTPUT=$(deck gateway diff \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  ${BACKUP_FILE})<br><br># Check if diff output shows no changes (all counts are 0)<br>if echo &quot;$DIFF_OUTPUT&quot; | grep -q &quot;Created: 0&quot; &amp;&amp; echo &quot;$DIFF_OUTPUT&quot; | grep -q &quot;Updated: 0&quot; &amp;&amp; echo &quot;$DIFF_OUTPUT&quot; | grep -q &quot;Deleted: 0&quot;; then<br>    echo &quot;No changes detected. Skipping sync.&quot;<br>else<br>    echo &quot;Changes detected. Synchronizing Kong Gateway configuration with Control Plane...&quot;<br>    deck gateway sync \<br>      --konnect-token-file ${TOKEN_FILE} \<br>      --konnect-control-plane-name ${CONTROL_PLANE} \<br>      --konnect-addr ${CONTROL_PLANE_ADDR} \<br>      ${BACKUP_FILE}<br>fi<br><br># Root directory of POC<br>cd ../../../</pre><p>The <em>sync.sh</em> script automates safe reconciliation between the local <em>backup.yaml</em> file and the live Kong Konnect <em>Routing </em>Control Plane. It first changes into the <em>kong/scripts/sync</em> directory and uses <em>yq</em> to read the <strong>token file</strong> path, <strong>Control Plane</strong> name, and <strong>Konnect API</strong> address from <em>config.yaml</em>, so the script remains reusable without hardcoding environment-specific values. It then verifies that <em>backup.yaml</em> exists and runs <em>deck</em> <em>gateway</em> <em>diff</em> to compare that local declarative state with the current live state of the Control Plane, storing the command output in the <em>DIFF_OUTPUT</em> shell variable. The conditional check uses <em>grep</em> <em>-q</em>, where <em>grep</em> searches text for a matching pattern and the <em>-q</em> flag means <em>quiet mode</em>, returning only a success or failure exit code without printing matching lines. In this script, <em>grep</em> <em>-q</em> checks whether the <em>diff</em> summary contains <em>Created:</em> <em>0</em>, <em>Updated:</em> <em>0</em>, and <em>Deleted:</em> <em>0</em>. If all three checks succeed, the script concludes that no drift exists between <em>backup.yaml</em> and the live <em>Routing</em> Control Plane and safely skips synchronization. If any one of those values is <em>non-zero</em>, the <em>bash script</em> in <em>sync.sh</em> detects configuration drift and runs <em>deck</em> <em>gateway</em> <em>sync</em> with <em>backup.yaml</em> as the declarative source, bringing the Kong Konnect <em>Routing</em> Control Plane back into alignment with the local <em>backup</em> file. This makes <em>sync.sh</em> a practical automation step for drift control, controlled reconciliation, and maintaining <em>backup.yaml</em> as the single source of truth.</p><p>Updated project folder structure after adding <em>sync.sh</em> to reconcile <em>backup.yaml</em> with the live configuration state of the Kong Konnect Control Plane:</p><pre>KongRouting/<br>├── .env<br>├── docker-compose.yaml<br>├── start.sh<br>└── kong/<br>    ├── echo/<br>    │   ├── config.yaml<br>    │   ├── echo.sh<br>    │   ├── echo.yaml<br>    │   ├── patches.yaml<br>    │   ├── request-termination.yaml<br>    │   └── spec.yaml<br>    ├── httpbin/<br>    │   ├── config.yaml<br>    │   ├── example.sh<br>    │   └── example.yaml<br>    ├── scripts/<br>    │   └── sync/<br>    │       ├── backup.yaml<br>    │       ├── config.yaml<br>    │       ├── kong_connect.sh<br>    │       ├── routing.deck.yaml<br>    │       └── sync.sh<br>    └── shared/<br>        ├── self_signed_certificate.sh<br>        ├── logs/<br>        │   ├── proxy_access.log<br>        │   ├── proxy_error.log<br>        │   ├── status_access.log<br>        │   └── status_error.log<br>        └── ssl/<br>            ├── cluster.crt<br>            ├── cluster.key<br>            ├── server.crt<br>            └── server.key</pre><h4>Synchronizing Backup</h4><p>Execute the <em>sync.sh</em> bash automation script from the root project directory <em>KongRouting</em> to synchronize the <em>backup.yaml</em> Kong declarative configuration with the Kong Konnect <em>Routing</em> Control Plane. Ensuring that the terminal session is positioned in the root project folder allows the script to correctly resolve all relative file paths and configuration references used during the synchronization workflow.</p><figure><img alt="The backup.yaml file acts as the source-of-truth Kong declarative configuration used to reconcile the Kong Konnect Routing Control Plane state." src="https://cdn-images-1.medium.com/max/1024/1*pLgur7p-WURX5onzqx8sxw.png" /><figcaption><strong>Syncing</strong> the local <strong>Kong declarative configuration</strong> in <strong>backup.yaml</strong> with Kong Konnect <strong>Routing</strong> <strong>Control Plane</strong></figcaption></figure><p>In this execution flow, the script first performs a configuration comparison using the <em>deck</em> gateway <em>diff</em> <em>deck</em> command instead of directly synchronizing the configuration. This helps prevent unnecessary synchronization operations when no configuration drift exists between the local backup artifact and the current state of the Control Plane.</p><p>The local <em>backup.yaml</em> declarative configuration is already fully synchronized with the Konnect <em>Routing</em> Control Plane. The script safely skips executing <em>deck</em> <em>gateway</em> <em>sync</em> <em>deck</em> command because no configuration differences were detected.</p><p>Let us try <strong>deleting</strong> the <em>echo-api-message</em> route of <em>echo-api</em> service from Kong Konnect UI in <em>Routing</em> Control Plane. Login to Kong Konnect Platform and from the API Gateway <strong>→</strong> Gateways navigation item on the left navigation pane navigate to the <em>Gateway manager</em> page in Kong Konnect.</p><figure><img alt="Kong Konnect Gateway manager. Select the Routing Control Plane from Kong Konnect UI in the Gateway manager page." src="https://cdn-images-1.medium.com/max/1024/1*0hS0VrQJgYcImGXtAEb0LQ.png" /><figcaption>Kong Konnect Gateway manager</figcaption></figure><p>Select the <em>Routing</em> Control Plane to list out navigation options on left navigation pane of the Kong Konnect UI for <strong>API Gateway </strong><strong>Routing</strong> Control Plane.</p><figure><img alt="Selecting echo-api-message route of echo-api Gateway service for deletion from Kong Konnect UI in the Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*VY1AQ4PayzrofXY1wIjesw.png" /><figcaption><strong>Delete</strong> <strong>echo-api-message</strong> <strong>Route</strong> of <strong>echo-api</strong> Service from Kong Konnect <strong>Routing Control Plane</strong></figcaption></figure><p>Navigate to the <strong>Gateway services</strong> page from the Gateway Services navigation item on the left navigation pane of Kong Konnect Routing Control Plane, select the <em>echo-api</em> Gateway service. In the <strong>Routes</strong> tab section of <em>echo-api</em> gateway service configuration page, click on the three dots on the right side of <em>echo-api-message</em> route opening a <strong>context-menu </strong>containing route management actions such as Edit and Delete. Select the Delete action from the <strong>context-menu</strong>.</p><figure><img alt="The Delete a route confirmation dialog requires the route name to be entered before the route can be permanently deleted from the Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*JXrMQwz0qTGhnuf0ULOuIQ.png" /><figcaption><strong>Confirming</strong> the <strong>Delete</strong> action on <strong>echo-api-message</strong> <strong>Route</strong></figcaption></figure><p>Selecting the Delete option from the route context-menu opens the <strong>Delete a route</strong> confirmation dialog, prompting the user to type the route name <em>echo-api-message</em> before permanently removing the Expressions route and its associated plugins if any from the Kong Konnect <em>Routing</em> Control Plane. Enter the route name <em>echo-api-message</em> and select the “<strong>Yes, delete</strong>” button.</p><figure><img alt="Successfully deleted the route echo-api-message of echo-api service in Kong Konnect Routing Control Plane from the Kong Konnect UI." src="https://cdn-images-1.medium.com/max/1024/1*BFwVERGTNxV7htaHa8dHvA.png" /><figcaption>The <strong>echo-api-message</strong> <strong>Route</strong> of <strong>echo-api</strong> Service <strong>Permanently deleted</strong> from Kong Konnect <strong>Routing</strong> <strong>Control Plane</strong></figcaption></figure><p>A notification message stating Successfully deleted route appears at the bottom-right corner of the page, confirming that the <em>echo-api-message</em> route associated with the <em>echo-api</em> Gateway service has been <strong>permanently</strong> deleted from the Kong Konnect <em>Routing</em> Control Plane.</p><p>Since the deletion operation was performed directly through the <strong>Kong Konnect UI</strong> instead of through the <strong>declarative </strong>configuration workflow managed by <em>decK</em>, a configuration drift now exists between the live state of the <em>Routing</em> Control Plane and the <strong>locally</strong> maintained <em>backup.yaml</em> Kong declarative configuration file. The local <em>backup.yaml</em> artifact still contains the deleted Expressions route definition, while the current <em>Routing</em> Control Plane configuration no longer contains that route entity.</p><p>After the configuration drift is introduced into the live Kong Konnect <em>Routing</em> Control Plane, execute the <em>sync.sh</em> Bash automation script again from the root project directory <em>KongRouting</em> to <strong>reconcile</strong> the current Control Plane state with the declarative configuration defined in <em>backup.yaml</em>.</p><figure><img alt="Terminal screenshot showing the output of running sync.sh. The visible lines read: “Checking for changes in backup.yaml…”, “Changes detected. Synchronizing Kong Gateway configuration with Control Plane”, and “creating route echo-api-message”, followed by a summary “Created: 1, Updated: 0, Deleted: 0”. This confirms the echo-api-message route has been successfully restored in the Konnect control plane." src="https://cdn-images-1.medium.com/max/1024/1*W1_Jnqglaxrdp96zxBggOQ.png" /><figcaption>The route <strong>echo-api-message</strong> <strong>re-created successfully</strong> associated with the <strong>echo-api</strong> gateway service in the Kong Konnect <strong>Routing Control Plane</strong></figcaption></figure><p>Running the <em>sync.sh</em> script again in the <em>KongRouting</em> directory shows that the <em>deck</em> tool detected configuration changes and re-applied them into the Kong Konnect <em>Routing</em> Control Plane. The output logs from the deck operations indicate that it is <em>creating route echo-api-message</em>, and the summary shows Created: 1, Updated: 0, Deleted: 0. This means exactly one new route (the <em>echo-api-message</em> route) was added, and none were changed or removed. In effect, the previously <strong>deleted</strong> route under the <em>echo-api</em>Gateway service has now been restored in Kong Konnect <em>Routing</em> Control Plane, bringing the live configuration back in line with the <em>backup.yaml</em> Kong declarative file.</p><figure><img alt="Re-synchronizing the backup.yaml file by executing the bash automation script sync.sh restores the echo-api-message route back to its original state successfuly in the Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*9pKDhF6YfrNSOzTOJmnIXw.png" /><figcaption>The <strong>echo-api-message</strong> <strong>route</strong> <strong>restored successfully</strong> into Kong Konnect <strong>Routing Control Plane</strong> with <strong>Expressions</strong> based <strong>Routing</strong></figcaption></figure><p>Synchronizing the backup eliminates any drift between the live Kong Konnect Control Plane state and the <em>backup</em> file <em>backup.yaml</em>. After this step, the live configuration matches exactly with the Kong declarative configurations defined in <em>backup.yaml</em>. The <em>deck</em> <em>gateway</em> <em>sync</em> <em>deck</em> command configures the Kong Konnect <em>Routing</em> Control Plane to mirror the provided declarative configuration as defined in the <em>backup</em>.</p><p>This synchronization approach demonstrates how Kong declarative configuration management with <em>decK</em> can be used to continuously enforce configuration consistency across Kong Konnect Control Plane environments. The <em>backup.yaml</em> file effectively becomes the single source of truth for the <em>Routing</em> Control Plane configuration, ensuring that the live <strong>Control Plane state</strong> can always be <strong>restored</strong>, <strong>reproduced</strong>, <strong>version-controlled</strong>, and <strong>audited</strong> through automated infrastructure workflows.</p><h3>Conclusion</h3><p>In this blog, we implemented an end-to-end Expressions Routing solution using Kong Gateway and Kong Konnect to filter and process incoming API requests based on the destination Gateway port numbers. By enabling the Expressions router through <em>KONG_ROUTER_FLAVOR=expressions</em> environment setting, the <em>Routing</em> Control Plane was able to leverage the powerful Expressions <strong>ATC</strong> router engine that matches requests using <strong>Kong’s Expressions language</strong> instead of the legacy traditional router logic, to create highly flexible and precise traffic matching rules using conditions such as <em>net.dst.port</em> <em>==</em> <em>443</em>.</p><p>The blog demonstrated how declarative API management using <em>decK</em> can automate the complete lifecycle of API onboarding, configuration validation, synchronization, backup management, and route restoration within the Kong Konnect <em>Routing</em> Control Plane. Through automated Bash scripting workflows, OpenAPI-driven onboarding, declarative patch transformations, and plugin injection, the <strong>entire routing solution was provisioned in a repeatable and GitOps-friendly manner</strong>.</p><figure><img alt="This solution summary demonstrates the use of expressions routing in Kong Gateway to filter incoming API requests by destination port number." src="https://cdn-images-1.medium.com/max/1024/1*Q2KfMHORZJLmQjVCOeZxSg.png" /><figcaption>Expressions Routing Summary</figcaption></figure><p>The implementation also showed how multiple HTTPS-enabled Kong Gateway ports can coexist within the same Kong Gateway Data Plane node while allowing Expressions routes to selectively process API traffic based on the destination port receiving the client request. This provides a powerful mechanism for implementing advanced routing strategies, API segregation patterns, environment isolation models, and API Gateway-level traffic control policies without relying solely on traditional path-based routing.</p><p>Additionally, the backup synchronization workflow highlighted how Kong declarative configuration artifacts such as the <em>backup.yaml</em> file can be used to continuously reconcile and restore the desired state of the Kong Konnect <em>Routing</em> Control Plane, ensuring configuration consistency and preventing drift caused by manual administrative changes.</p><p>By combining Expressions Routing, Konnect-managed Control Plane, declarative configuration management, Docker Compose automation, TLS-secured Kong Gateway endpoints, and bash automated synchronization workflows, Kong Konnect provides a robust SaaS based API platform for building scalable, secure, and operationally consistent API Gateway architectures for modern cloud-native environments.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=83a4cef197ee" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port…]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-611822f26fc2?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/611822f26fc2</guid>
            <category><![CDATA[api-gateway]]></category>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[bash]]></category>
            <category><![CDATA[kong-konnect]]></category>
            <category><![CDATA[deck]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Mon, 11 May 2026 12:44:36 GMT</pubDate>
            <atom:updated>2026-05-11T12:52:05.667Z</atom:updated>
            <cc:license>https://creativecommons.org/licenses/by-nc-nd/4.0/</cc:license>
            <content:encoded><![CDATA[<h3><strong>Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port Number — Part-3</strong></h3><figure><img alt="Technical banner illustration showing a Kong Konnect-managed Kong Gateway Enterprise Data Plane filtering inbound API requests by destination port number using Kong Expressions Routing." src="https://cdn-images-1.medium.com/max/1024/1*WVsdSOc4qxkak5mH8hd0og.png" /><figcaption>Kong Konnect-managed Kong Gateway Enterprise, filtering inbound API requests by destination port number</figcaption></figure><p>Shubhojit Dasgupta — Independent API Architect</p><p><a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-dde0a6af8c13"><strong>Part-2</strong></a> of this blog series established the operational foundation for integrating a self-managed Kong Gateway Data Plane with the Kong Konnect Control Plane. We provisioned the Kong Konnect Control Plane, installed and configured the self-managed Kong Gateway runtime, generated and uploaded a self-signed TLS certificate into the Kong Konnect Platform, and validated the operational behavior of the Kong Gateway Proxy and Status API endpoints.</p><p>In this part of the blog series, we will onboard the <strong>Kong echo API</strong> and <strong>HTTPBin API</strong> backend services into the Kong Konnect <em>Routing</em> Control Plane using automated Bash scripting and multiple decK operations. We will convert the echo API OpenAPI specification into Kong declarative configuration, patch the generated configuration using automation to onboard services, transform traditional routes to expressions based routes, and inject the <strong>Request-Termination plugin</strong> declaratively, and repeat the same automated onboarding workflow for the HTTPBin API service. Finally, we will refresh the backup.yaml configuration to confirm <em>zero-drift</em> <strong>synchronization</strong>, ensuring the Kong Konnect configuration state defined in backup.yaml file remains the single source of truth for the live Routing Control Plane.</p><h3>Onboarding echo API Service</h3><p>Create a folder named echo within the kong directory of the project. This folder contains all configuration assets required to provision, configure, and onboard the Echo API service into the Kong Konnect Control Plane.</p><p>The Echo API is exposed to client applications securely through the Kong Gateway using the <strong>HTTPS listener on port 443</strong>. To access the service, client applications must send HTTPS API requests to Kong Gateway endpoint on port 443, where the request is evaluated by the Expressions router before being forwarded to the upstream Echo API service.</p><p>To demonstrate Expressions-based routing in Kong Gateway, a lightweight Echo API service is deployed as a backend upstream application. The Echo service is useful for testing because it returns request details such as headers, protocol information, and request metadata, making it easier to verify how incoming traffic is processed and routed through the gateway.</p><p>The Echo API container is deployed alongside the Kong Gateway Data Plane within the same Docker network, enabling seamless internal communication between the Kong Gateway and the upstream service.</p><h4>Echo API Docker Compose Service Definition</h4><pre>kongecho:<br>  networks:<br>    - ${NETWORK}<br>  image: kong/go-echo:latest<br>  container_name: kongecho<br>  hostname: konglocalecho<br>  restart: on-failure<br>  ports:<br>    - &#39;${TCP_PORT}:1025/tcp&#39;<br>    - &#39;${UDP_PORT}:1026/udp&#39;<br>    - &#39;${HTTP_PORT}:1027&#39;</pre><h4><strong>Service Configuration Overview</strong></h4><p>● <strong>Docker Network Integration</strong>: The Echo API service is attached to the same Docker bridge network as the Kong Gateway Data Plane, allowing the gateway to route requests internally using container DNS resolution.</p><p>● <strong>Official Kong Echo Image</strong>: The service uses the official <em>kong/go-echo:latest</em> container image, which provides a lightweight API endpoint for testing HTTP, TCP, and UDP traffic flows.</p><p>●<strong>Container Identity</strong>: The <em>container_name</em> &amp; <em>hostname</em> values establish a predictable network identity for service discovery within the Docker network.</p><p>● <strong>Automatic Restart Policy</strong>: The <em>on-failure</em> restart policy ensures that the container is automatically restarted if the service exits unexpectedly.</p><p>● <strong>Multi-Protocol Port Exposure</strong>: The Echo API exposes:</p><p>○ TCP traffic on port 1025</p><p>○ UDP traffic on port 1026</p><p>○ HTTP traffic on port 1027</p><p>These ports are mapped dynamically using environment variables defined in the <em>.env</em> file for echo API service, enabling flexible local development and testing.</p><p>Add the Docker Compose Service definition of echo API into <em>docker-compose.yaml</em> file, below the service definition for <em>kong-dp</em>. The environment variables used in echo API Docker Compose service definition is added to the <em>.env</em> file.</p><pre># Kong echo API configurations<br>TCP_PORT=1024<br>UDP_PORT=1026<br>HTTP_PORT=1027</pre><h4>Installing Kong echo service</h4><p>In the root <em>KongRouting</em> folder of the project execute the <em>start.sh</em> bash file from the terminal. Ensure that the root folder of the project is the current working directory in the terminal while executing the command to run the bash script.</p><figure><img alt="Starting the container for Kong echo service." src="https://cdn-images-1.medium.com/max/1024/1*9RzrkTbPCByolHSep200qQ.png" /><figcaption>Starting kongecho service container</figcaption></figure><p>Once the container is up, it becomes the local upstream service that Kong Gateway will proxy to when the <em>/echo</em> route matches on the correct destination port. Bringing this service online is a prerequisite for validating end-to-end request flow through Kong (client → gateway → upstream) and confirming that Expressions routing is working as expected.</p><p><strong>Control Plane Configuration</strong></p><p>The <em>config.yaml</em> file created in the echo<strong> </strong>directory of the project, defines the connection settings required for interacting with the Kong Konnect Control Plane using <strong>decK</strong> commands. This configuration externalizes Control Plane details from scripts and decK commands, making the onboarding workflow reusable, portable, and easier to maintain across environments.</p><p><strong>File</strong> config.yaml:</p><pre># Kong Konnect Routing Control Plane<br>konnect_addr: https://in.api.konghq.com<br>control_plane: Routing <br>token_file: ../scripts/sync/routing.deck.yaml</pre><p><strong>Configuration Parameters:</strong></p><p>● <strong>konnect_addr</strong>: Specifies the regional Konnect API endpoint used by decK to communicate with the Kong Konnect Control Plane. The <em>konnect_addr:</em> <a href="https://in.api.konghq.com/"><em>https://in.api.konghq.com</em></a> provides India-region Konnect endpoint used for Control Plane operations.</p><p>● <strong>The control_plane</strong>: Defines the name of the target Control Plane where API entities such as Services, Routes, Plugins, and Certificates will be provisioned. The value <em>control_plane:</em> <em>Routing</em> must match the Control Plane Name created earlier in the Konnect UI.</p><p>● <strong>The token_file: </strong>References the file containing the Konnect Personal Access Token used for authentication. The mapping <em>token_file:</em> <em>../scripts/sync/routing.deck.yaml</em> references <em>routing.deck.yaml</em> file. This file stores the token securely and is consumed by decK commands during synchronization and validation operations.</p><p>This approach promotes a cleaner separation between operational scripts and environment-specific configuration.</p><h4>OpenAPI Specification</h4><p>The OpenAPI YAML specification file <em>spec.yaml</em>, created in the echo<strong> </strong>directory of the project, defines the contract for the echo API service that will be onboarded into Kong Konnect using decK. The <em>spec.yaml</em> file uses <strong>OpenAPI 3.1.0 specification format</strong>, enabling standard tooling support for docs and automation (as indicated by <em>openapi:</em> <em>3.1.0</em>).</p><p><strong>File</strong> spec.yaml:</p><pre>openapi: 3.1.0<br>info:<br>  title: Kong Echo API<br>  description: API specification for the Kong Echo service.<br>  version: 1.0.0<br>servers:<br>  - url: https://localhost<br>    description: Local internal server for Kong Echo<br>paths:<br>  /favicon.ico:<br>    get:<br>      summary: Get favicon with termination plugin<br>      description: Returns the favicon image for the service, with a kong request termination plugin returning 204 No Content.<br>      operationId: favicon<br>      tags:<br>        - Assets<br>      responses:<br>        &#39;204&#39;:<br>          description: No Content. Request terminated by plugin.<br>        &#39;200&#39;:<br>          description: Favicon image returned successfully.<br>          content:<br>            image/x-icon:<br>              schema:<br>                type: string<br>                format: binary<br>            image/png:<br>              schema:<br>                type: string<br>                format: binary<br>            image/jpeg:<br>              schema:<br>                type: string<br>                format: binary<br>            image/gif:<br>              schema:<br>                type: string<br>                format: binary<br>            image/svg+xml:<br>              schema:<br>                type: string<br>                format: binary<br>  /echo: <br>    get:<br>      summary: Echo a message<br>      description: Accepts a JSON payload with a message and echoes it back.<br>      operationId: echoMessage<br>      tags:<br>        - Echo<br>      requestBody:<br>        required: false<br>        content:<br>          application/json:<br>            schema:<br>              $ref: &quot;#/components/schemas/EchoRequest&quot;<br>            example:<br>              message: &quot;Hello, Echo!&quot;<br>      responses:<br>        &#39;200&#39;:<br>          description: Message echoed successfully.<br>          content:<br>            application/json:<br>              schema:<br>                $ref: &quot;#/components/schemas/EchoResponse&quot;<br>              example:<br>                message: &quot;Hello, Echo!&quot;<br>components:<br>  schemas:<br>    EchoRequest:<br>      type: object<br>      properties:<br>        message:<br>          type: string<br>          description: A message to be echoed back.<br>          example: &quot;Hello, Echo!&quot;<br>    EchoResponse:<br>      type: object<br>      properties:<br>        message:<br>          type: string<br>          description: The echoed message.<br>          example: &quot;Hello, Echo!&quot;<br>tags:<br>  - name: Assets<br>    description: Operations related to static assets like favicons.<br>  - name: Echo<br>    description: Operations related to echoing messages.</pre><p>The OpenAPI specification for Kong Echo API defines two primary <strong>GET</strong> endpoints:</p><p>1. The <em>/favicon.ico</em> path, for handling browser favicon requests efficiently</p><p>2. The <em>/echo</em> path, for accepting JSON REST API requests via the Kong Gateway and echoing back to the client</p><p>This specification acts as the foundational API definition from which Kong entities such as <strong>Services</strong>, <strong>Routes</strong>, and associated <strong>policies</strong> can be generated and managed declaratively via decK. The <em>spec.yaml</em> file serves as the primary input artifact for the onboarding workflow. It is processed through multiple decK operations defined in the <em>echo.sh</em> bash file.</p><h4>Architecture Overview</h4><figure><img alt="Architectural Overview Depicting the Onboarding of echo API into Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*KQ-PPlgtNlgWWlqnnRUm7w.png" /><figcaption>Onboarding echo API into Kong Konnect Routing Control Plane</figcaption></figure><h4>Automated Bash Script</h4><p>Create <em>echo.sh</em> in the echo directory. This script runs the decK commands to onboard echo API into <strong>Kong Konnect </strong><em>Routing </em><strong>Control Plane</strong>, using the OpenAPI specification of <strong>echo API</strong> in <em>spec.yaml</em> file as the input and generating the Kong declarative configuration file <em>echo.yaml</em> in the same directory.</p><p>This script orchestrates the complete onboarding workflow using <strong>decK</strong> <strong>commands</strong>, transforming the OpenAPI specification of echo API into a valid Kong Declarative Configuration, applying Expressions-based routing policies, validating the generated configuration, synchronizing it with the Routing Control Plane, and creating a backup artifact for recovery purposes.</p><p><strong>File</strong> echo.sh:</p><pre>#! /usr/bin/env bash<br><br># Directory in which the deck connect script runs<br>cd kong/echo<br><br># Importing configuration variables<br>CONTROL_PLANE=$(yq e &#39;.control_plane&#39; ./config.yaml)<br>CONTROL_PLANE_ADDR=$(yq e &#39;.konnect_addr&#39; ./config.yaml)<br>TOKEN_FILE=$(yq e &#39;.token_file&#39; ./config.yaml)<br><br># Convert openapi to decK configuration<br>deck file openapi2kong \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  -s spec.yaml \<br>  -o echo.yaml<br><br># Applying patches to the generated Kong Declarative Config for Echo API<br>deck file patch \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  -s echo.yaml -o echo.yaml \<br>  patches.yaml<br><br># Add request-termination plugin<br>deck file add-plugins \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  -s echo.yaml -o echo.yaml \<br>  request-termination.yaml<br><br># Preview changes made by echo API before applying<br>deck gateway diff \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  echo.yaml<br><br># Validate the echo API configuration before applying<br>deck gateway validate \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  echo.yaml<br><br># Apply echo API configuration in Kong Konnect<br>deck gateway apply \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  echo.yaml<br><br># Backup echo API configuration in Kong Konnect<br>deck gateway dump \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  -o ../scripts/sync/backup.yaml<br><br># Validate the backup configuration<br>deck gateway validate \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  ../scripts/sync/backup.yaml<br><br># Preview changes made by backup configuration before syncing<br>deck gateway diff \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR} \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  ../scripts/sync/backup.yaml<br><br>echo &quot;Applied Kong Konnect echo API configuration into ${CONTROL_PLANE} Control Plane.&quot;<br># Root directory<br>cd ../..</pre><p>The automation eliminates manual configuration steps and enables repeatable onboarding workflows that integrate well with GitOps and APIOps delivery pipelines. The bash script in <em>echo.sh</em> file reads the variables from <em>config.yaml</em> file in the echo directory fetching the Control Plane name, API address, and the path of the Kong Konnect Personal access token file <em>routing.deck.yaml</em> in the <em>/scripts/sync</em> directory of the project.</p><p>The onboarding workflow begins with the deck file openapi2kong command converting the OpenAPI specification of echo API in <em>spec.yaml</em> file into a Kong Declarative Configuration file <em>echo.yaml</em> in the same echo directory.</p><p>During the conversion process, decK automatically generates predictable names for Services and Routes. The Kong Service name for echo API is derived from the <em>info.title</em> section of the OpenAPI spec (<strong>Kong Echo API</strong>) in <em>spec.yaml</em> file. The decK command normalizes it (lowercase + hyphens), so Kong Echo API becomes <em>kong-echo-api</em> in <em>echo.yaml</em>.</p><p>In the Echo API OpenAPI spec (<em>spec.yaml</em>), each <strong>path + operation</strong> is converted by <strong>decK</strong> into a <strong>traditional Kong Route</strong>. decK constructs each Route name by concatenating the generated Kong Service name from <em>echo.yaml</em> with the operation’s <em>operationId</em> from the paths section of <em>spec.yaml</em>, using an underscore (<strong>_</strong>) as the separator.</p><p><strong>Example: </strong><em>/favicon.ico</em></p><pre>operationId: favicon<br>Route name: kong-echo-api_favicon</pre><p><strong>Example: </strong><em>/echo</em></p><pre>operationId: echoMessage<br>Route name: kong-echo-api_echomessage</pre><p>These deterministic Route names are later referenced by the patching step to selectively transform the generated traditional Routes into <strong>Expressions</strong> Routes. In the echo directory create the file <em>patches.yaml</em>.</p><p><strong>Patching openapi2kong Output for Expressions Routing</strong></p><p>The <em>openapi2kong</em> step initially produces <strong>traditional</strong> Kong Routes based on <em>paths</em> and <em>methods</em>. This blog demonstrates <strong>Expressions routing</strong> with port-based filtering (net.dst.port), hence we use <em>deck file patch</em> with <em>patches.yaml</em> to transform the generated config <em>echo.yaml</em> in-place.</p><p>● The<strong> selectors</strong> section use JSONPath syntax to find the exact objects to modify (for example, routes named <em>kong-echo-api_favicon</em> and <em>kong-echo-api_echomessage</em>). The predictable names generated by <em>openapi2kong</em> make these targets reliable.</p><p>● The<strong> values</strong> section overwrites fields to create <strong>Expressions</strong> routes. It renames the routes, adds an <em>expression</em> that matches <em>http.method</em>, prefix-based <em>http.path</em>, and the destination listener port (net.dst.port == 443), and applies a common <em>echo</em> tag. Tags help grouping/filtering in Konnect and in dumps.</p><p>● The<strong> remove </strong>section deletes <em>paths</em> and <em>methods</em> from the traditional routes so the Expressions router evaluates only the <em>expression</em> condition.</p><p>● The <strong>service</strong> selector retargets the generated upstream to the local Docker service by setting <em>protocol</em>, <em>host</em>(<em>kongecho</em>), and <em>port</em> (<em>1027</em>), and removes any default <em>path</em>. Because Kong and Echo run on the same Docker network, <em>kongecho</em> resolves automatically via Docker DNS.</p><p><strong>File</strong> patches.yaml:</p><pre>patches:<br>  - selectors:<br>      - $..routes[?(@.name==&#39;kong-echo-api_favicon&#39;)]<br>    values:<br>      name: echo-api-favicon<br>      expression: &gt;-<br>        http.method == &quot;GET&quot; &amp;&amp; <br>        http.path ^= &quot;/favicon.ico&quot; &amp;&amp; <br>        net.dst.port == 443<br>      strip_path: false<br>      tags:<br>        - echo<br>    remove:<br>      - paths<br>      - methods<br>  - selectors:<br>      - $..routes[?(@.name==&#39;kong-echo-api_echomessage&#39;)]<br>    values:<br>      name: echo-api-message<br>      expression: &gt;-<br>        http.method == &quot;GET&quot; &amp;&amp; <br>        http.path ^= &quot;/echo&quot; &amp;&amp; <br>        net.dst.port == 443<br>      strip_path: false<br>      tags:<br>        - echo<br>    remove:<br>      - paths<br>      - methods<br>  - selectors:<br>      - $..services[?(@.name==&#39;kong-echo-api&#39;)]<br>    values:<br>      name: echo-api<br>      protocol: http<br>      port: 1027<br>      host: kongecho<br>      tags:<br>        - echo<br>    remove:<br>      - path</pre><p>The recursive descent operator (<strong>..</strong>) is important because the generated Kong declarative configuration may contain nested structures. Using <strong>..</strong> ensures that the selector can locate matching entities regardless of where they appear in the document hierarchy. For example in the <em>patches.yaml</em> file - $..routes[?(@.name==’kong-echo-api_favicon’)] searches for a route named <em>kong-echo-api_favicon</em> anywhere in the generated <em>echo.yaml</em>, regardless of whether routes appear at the top level or are nested under sections like <em>_format_version</em> or <em>services</em>. After patching, the transformed <em>echo.yaml</em> will contain the renamed Routes configured for Expressions routing (with <em>expression</em> conditions such as net.dst.port == 443), ready to be synchronized to Konnect.</p><h4>Injecting Request-Termination Plugin</h4><p>After transforming the traditional routes into Expressions-based routes, a <em>request-termination.yaml</em> file is created inside the <em>kong/echo</em> directory to declaratively inject the <strong>request-termination</strong> plugin into the <em>favicon</em> route. This plugin is attached specifically to the Expressions route matching the name <em>echo-api-favicon</em> using a JSONPath selector $..routes[?(@.name==’echo-api-favicon’)]. The selector recursively searches <em>echo.yaml</em> decK file and locates the <strong>target route</strong> by name. The request-termination plugin configuration returns HTTP 204 No Content for API requests to<em>/favicon.ico</em> on destination port <strong>443,</strong>based on the expression: <em>http.method</em> <em>==</em> <em>“GET”</em> <em>&amp;&amp;</em> <em>http.path</em> <em>^=</em> <em>“/favicon.ico”</em> <em>&amp;&amp;</em> <em>net.dst.port==</em> <em>443</em> for <em>echo-api-favicon</em> route. The request is never forwarded to the upstream echo API service.</p><p>This helps avoid unnecessary upstream calls via Kong generated automatically by browsers requesting favicon assets.</p><p><strong>File</strong> request-termination.yaml:</p><pre># request-termination.yaml<br>add-plugins:<br>  - selectors:<br>      - $..routes[?(@.name==&#39;echo-api-favicon&#39;)]<br>    overwrite: false<br>    plugins:<br>      - name: request-termination<br>        config:<br>          status_code: 204</pre><p>Because the <strong>request-termination</strong> plugin returns a 204 (No Content), the response contains no body and the request is handled entirely at the gateway without calling the upstream Echo service. The <em>deck</em> <em>file</em> <em>add-plugins </em>command injects the plugin defined in <em>request-termination.yaml</em> file into the <em>echo.yaml</em> declarative config, updating the file in place.</p><p>Updated Project Folder Structure after adding files for onboarding echo API service into Kong Konnect Control Plane:</p><pre>KongRouting/<br>├── .env<br>├── docker-compose.yaml<br>├── start.sh<br>└── kong/<br>    ├── echo/<br>    │   ├── config.yaml<br>    │   ├── spec.yaml<br>    │   ├── patches.yaml<br>    │   ├── request-termination.yaml<br>    │   ├── echo.yaml<br>    │   └── echo.sh<br>    │<br>    ├── scripts/<br>    │   └── sync/<br>    │       ├── config.yaml<br>    │       ├── kong_connect.sh<br>    │       ├── routing.deck.yaml<br>    │       └── backup.yaml<br>    │<br>    └── shared/<br>        ├── self_signed_certificate.sh<br>        │<br>        ├── logs/<br>        │   ├── proxy_access.log<br>        │   ├── proxy_error.log<br>        │   ├── status_access.log<br>        │   └── status_error.log<br>        │<br>        └── ssl/<br>            ├── server.crt<br>            ├── server.key<br>            ├── cluster.crt<br>            └── cluster.key</pre><h4>Executing the Bash Script</h4><p>Executing the bash script defined in <em>echo.sh</em> file will synchronize the generated Kong Declarative Configuration file <em>echo.yaml</em> with the Kong Konnect <strong>Routing</strong> Control Plane. Once executed successfully, the echo API configuration is synchronised into the <em>Routing</em> Control Plane and automatically propagated to the connected Kong Gateway Data Plane.</p><figure><img alt="Empty Gateway services page in Kong Konnect UI as No APIs have been onboarded into the Kong Konnect Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*nedZk_zWrlRQdt8-LiYB1g.png" /><figcaption>Kong Konnect Gateway services Page Empty</figcaption></figure><p>The Gateway services page in Kong Konnect is empty, as no APIs have been onboarded into Kong Konnect <em>Routing </em>Control Plane. In the terminal, with <em>KongRouting</em> project root folder as the current working directory, run <em>echo.sh</em> file.</p><figure><img alt="Applying the configurations for service, routes, and plugin as defined in Kong echo API into Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*IzIQ270zfz0Bv-vTdMBPZQ.png" /><figcaption><strong>Onboarding</strong> services, routes and plugin configurations of <strong>Kong echo API</strong> into Kong Konnect Routing Control Plane</figcaption></figure><p>The output from the execution of the bash script in <em>echo.sh</em> file is sent to the stdout of the terminal. The output from the <strong>deck</strong> operations show that it’s creating the service <em>echo-api</em> with two routes along with a request-termination plugin for <em>echo-api-favicon</em> route but the output also show that it is <em>deleting</em> <em>sni</em> <em>localhost</em> and <em>certificate</em> added earlier in the blog from the Kong Konnect UI in Certificates page.</p><p>Since the <em>echo.yaml</em> declarative configuration does not include the certificate and SNI created earlier in Kong Konnect, decK detects them as differences between the local file and the current state of the <em>Routing</em> Control Plane. This is why the <em>deck</em> <em>gateway</em> <em>diff</em> output shows those resources as candidates for deletion. The <em>deck</em> <em>gateway</em> <em>diff</em> command is only a <strong>dry run</strong>, so it does not apply any changes. Instead, it previews what would happen if <em>echo.yaml</em> were synchronized with the Kong Konnect <em>Routing</em> Control Plane.</p><p>To safely synchronize only the Echo API entities generated in <em>echo.yaml</em>, the workflow uses <em>deck gateway apply</em> rather than a full destructive sync. This is important because the goal at this stage is to add the new <em>echo-api</em> service, its two routes, and the <em>request-termination</em> plugin to the current Kong Konnect <em>Routing</em> Control Plane without removing the certificate and <em>localhost</em> SNI that were previously configured from the Kong Konnect UI. After those changes are applied, a backup of the live Control Plane state is immediately created and stored as <em>backup.yaml</em> in the <em>/scripts/sync</em> directory of the project using the <em>deck gateway dump</em> command. This generated <em>backup.yaml</em> file contains both sets of live configuration: the entities added by onboarding the Echo API and the certificate and SNI that were configured earlier from the Certificates page in Kong Konnect UI. When <em>deck</em> <em>gateway</em> <em>diff</em> is then executed against <em>backup.yaml</em>, the output summary shows <em>0 Kong entities created, updated, and deleted</em>, confirming that the local backup file exactly matches the current live state of the Kong Konnect <em>Routing </em>Control Plane. This makes <em>backup.yaml</em> in the <em>sync</em> directory the single source of truth for the current runtime configuration of the live Kong Konnect <em>Routing</em> Control Plane.</p><figure><img alt="The Kong Gateway Service for echo API onboarded into Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*SeXdctLu9XD2FMMogH3glg.png" /><figcaption>Kong Konnect Gateway services Page showing <strong>Kong echo-api Service </strong>Onboarded into Kong Konnect Routing Control Plane</figcaption></figure><figure><img alt="The routes defined in echo API have been onboarded into Kong Konnect Routing Control Plane as Kong Route objects." src="https://cdn-images-1.medium.com/max/1024/1*0QRHxJjh_FXIruZIJ3x7Rg.png" /><figcaption>Kong Konnect Gateway Routes for echo API Onboarded into Kong Konnect Routing Control Plane</figcaption></figure><p>The routes shown above are onboarded as <strong>Expressions</strong>-based routes rather than traditional path-only routes. This means each route evaluates not just the request path and HTTP method, but also the gateway destination port before traffic is forwarded upstream. In this setup, the <em>echo-api-message</em> route matches <em>GET</em> requests whose path starts with <em>/echo</em> and that arrive on port <em>443</em>, while the <em>echo-api-favicon</em> route matches browser requests to <em>/favicon.ico</em> on the same port. By encoding these conditions directly in the route expressions, Kong Gateway can accurately filter incoming API traffic and send only valid matching requests to the <em>echo-api</em> service upstream.</p><figure><img alt="The Request-Termination Plugin Added to echo API route echo-api-favicon in Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*RrBm100SKYSVMZx5BVzViw.png" /><figcaption><strong>Request-Termination</strong> Plugin Added to the Route echo-api-favicon of <strong>echo API</strong> service in Kong Konnect<strong> Routing</strong> <strong>Control Plane</strong></figcaption></figure><p>With this, the onboarding of the <em>echo API</em> into the Kong Konnect <em>Routing</em> Control Plane is complete. The service, its Expressions-based routes, and the <em>request-termination</em> plugin are now declaratively managed, synchronized to the live Control Plane, and propagated to the connected Kong Gateway Data Plane. At this point, the Echo API is no longer just defined on paper it is live, governed, and ready to prove how Expressions routing in Kong Gateway can enforce precise, port-aware traffic control in a real deployment.</p><h3>Onboarding HTTPBin API Service</h3><p>Create a folder httpbin under the kong directory of the project. The folder includes all the files related to the onboarding of HTTPBin API service into Kong Konnect <em>Routing</em> Control Plane as an <em>example-service</em> in Kong Konnect.</p><p>The <strong>HTTPBin API</strong> service is used in this routing demonstration as a lightweight upstream testing service behind the Kong Gateway.</p><p>The endpoint <em>/status/(?P&lt;status_code&gt;[1–5]\d{2})</em> dynamically returns HTTP response codes ranging from 100 to 599, making it useful for validating Expressions-based routing behavior, error handling, response propagation, and Gateway policy execution. The <em>/anything</em> endpoint accepts requests using any <strong>HTTP method</strong> and returns complete request metadata including headers, query parameters, payloads, and request details. This makes it ideal for verifying how client API requests are received, processed, and forwarded through the Kong Gateway Data Plane when filtering traffic based on destination gateway port numbers.</p><h4>Control Plane Configuration</h4><p>The <em>config.yaml</em> file created in the <strong>httpbin</strong> folder externalizes the Kong Konnect connection details required by decK. Keeping these values in a small configuration file avoids hardcoding environment-specific parameters inside the automation script and makes the onboarding flow easier to reuse across environments. In this file, <em>konnect_addr</em> points decK to the India-region Konnect API endpoint, <em>control_plane</em> identifies the target Control Plane as <em>Routing</em>, and <em>token_file </em>references the Personal Access Token file stored under <em>..</em><em>/scripts/sync</em>. The file content is shown below.</p><p><strong>File</strong> config.yaml:</p><pre># Kong Konnect Routing Control Plane<br>konnect_addr: https://in.api.konghq.com<br>control_plane: Routing<br>token_file: ../scripts/sync/routing.deck.yaml</pre><h4>Initial Kong Declarative Configuration</h4><p>The next artifact created in the httpbin folder is <em>example.yaml</em>, the initial Kong declarative configuration that will be synchronized into the Control Plane. Unlike the Echo API flow, this onboarding starts directly from a hand-authored decK state file rather than generating configuration from an OpenAPI specification. The file defines a single upstream service named <em>example-service</em> that proxies to <a href="https://httpbin.konghq.com,"><em>https://httpbin.konghq.com</em>,</a> along with two Expressions-based routes. One route handles business traffic for <em>/status/&lt;code&gt;</em> and <em>/anything</em> only when requests arrive on destination port <em>8443</em>, while the second route catches <em>/favicon.ico</em> requests and terminates them at the gateway using the <em>request-termination</em> plugin. This <em>example.yaml</em> file becomes the initial input to the automation script <em>example.sh</em>.</p><p><strong>File</strong> example.yaml:</p><pre>_format_version: &quot;3.0&quot;<br>services:<br>- name: example-service<br>tags:<br>- example<br>url: https://httpbin.konghq.com<br>routes:<br>- name: example-status-route<br>expression: (http.path ~ r#&quot;^/status/(?P&lt;status_code&gt;[1-5]\d{2})$&quot;# || http.path ^= &quot;/anything&quot;) &amp;&amp; net.dst.port == 8443<br>strip_path: false<br>tags:<br>- example<br>- name: example-favicon-route<br>expression: http.path ^= &quot;/favicon.ico&quot; &amp;&amp; net.dst.port == 8443<br>strip_path: false<br>tags:<br>- example<br>plugins:<br>- name: request-termination<br>config:<br>status_code: 200<br>message: &quot;Request terminated by plugin.&quot;<br>echo: true<br>tags:<br>- example</pre><h4>Architecture Overview</h4><figure><img alt="The Architecture Overview of How HTTPBin API is Onboarded into Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*dLDGhE3ptwhY_VJag9-dTw.png" /><figcaption>HTTPBin API Onboarding Architecture into Kong Konnect Routing Control Plane</figcaption></figure><h4>Deploying HTTPBin API using Automated Bash Script</h4><p>To automate the full onboarding flow, create a bash script named <em>example.sh</em> in the same httpbin folder. This script begins by switching into the kong<em>/</em><em>httpbin</em> directory and then uses <em>yq</em> to read the values of <em>control_plane</em>, <em>konnect_addr</em>, and <em>token_file </em>from <em>config.yaml</em>. Those values are assigned to shell variables and <strong>reused</strong> across all <strong>decK</strong> commands, which keeps the script concise and prevents duplication of configuration values. The declarative file <em>example.yaml</em> is then used as the source of truth for the initial apply operation.</p><p><strong>File</strong> example.sh:</p><pre>#! /usr/bin/env bash<br> <br># Directory in which the deck connect script runs<br>cd kong/httpbin<br> <br># Importing configuration variables<br>CONTROL_PLANE=$(yq e &#39;.control_plane&#39; ./config.yaml)<br>CONTROL_PLANE_ADDR=$(yq e &#39;.konnect_addr&#39; ./config.yaml)<br>TOKEN_FILE=$(yq e &#39;.token_file&#39; ./config.yaml)<br> <br># Preview changes made by example configuration before applying<br>deck gateway diff \<br>--konnect-control-plane-name ${CONTROL_PLANE} \<br>--konnect-addr ${CONTROL_PLANE_ADDR} \<br>--konnect-token-file ${TOKEN_FILE} \<br>example.yaml<br> <br># Validate the example configuration before applying<br>deck gateway validate \<br>--konnect-control-plane-name ${CONTROL_PLANE} \<br>--konnect-addr ${CONTROL_PLANE_ADDR} \<br>--konnect-token-file ${TOKEN_FILE} \<br>example.yaml<br> <br># Apply example configuration in Kong Konnect<br>deck gateway apply \<br>--konnect-control-plane-name ${CONTROL_PLANE} \<br>--konnect-addr ${CONTROL_PLANE_ADDR} \<br>--konnect-token-file ${TOKEN_FILE} \<br>example.yaml<br> <br># Backup configuration in Kong Konnect<br>deck gateway dump \<br>--konnect-control-plane-name ${CONTROL_PLANE} \<br>--konnect-addr ${CONTROL_PLANE_ADDR} \<br>--konnect-token-file ${TOKEN_FILE} \<br>-o ../scripts/sync/backup.yaml<br> <br># Validate the backup configuration<br>deck gateway validate \<br>--konnect-control-plane-name ${CONTROL_PLANE} \<br>--konnect-addr ${CONTROL_PLANE_ADDR} \<br>--konnect-token-file ${TOKEN_FILE} \<br>../scripts/sync/backup.yaml<br> <br># Preview changes made by backup configuration before syncing<br>deck gateway diff \<br>--konnect-control-plane-name ${CONTROL_PLANE} \<br>--konnect-addr ${CONTROL_PLANE_ADDR} \<br>--konnect-token-file ${TOKEN_FILE} \<br>../scripts/sync/backup.yaml<br> <br>echo &quot;Applied Kong Konnect example configuration into Konnect ${CONTROL_PLANE} Control Plane.&quot;<br># Root directory<br>cd ../..</pre><p><strong>Injecting Request-Termination Plugin</strong></p><p>With the <em>example-favicon-route</em> in place to catch all <em>/favicon.ico</em> requests arriving on port <strong>8443</strong>, the next step is to decide what Kong Gateway should actually <em>do</em> with them and that’s where the <strong>Request-Termination plugin</strong> comes in.</p><p>Rather than forwarding these browser-generated noise requests to your upstream service, the plugin intercepts them and immediately returns a response — no upstream call made, no backend resources consumed.</p><p>In this configuration, the plugin is set to respond with a 200 OK status code and a message of Request terminated by plugin.. This keeps browsers happy without triggering any errors. What makes this setup particularly interesting is the <em>echo:</em> <em>true</em> flag. When enabled, the plugin mirrors a copy of the incoming request back to the client, making it an excellent tool for <strong>debugging live traffic</strong> without disturbing real upstream <strong>HTTPBin API</strong> service.</p><p>It’s worth noting that the Request Termination plugin runs at <strong>priority 2</strong>, the lowest of all plugins (except Post-Function) — meaning all other plugins will execute first before the request is terminated.</p><pre>plugins:<br>  - name: request-termination<br>    config:<br>      status_code: 200<br>      message: &quot;Request terminated by plugin.&quot;<br>      echo: true<br>    tags:<br>      - example</pre><p>Updated project working directory after adding files for <strong>HTTPBin API</strong> service into Kong Konnect Control Plane:</p><pre>KongRouting/<br>├── .env<br>├── docker-compose.yaml<br>├── start.sh<br>└── kong/<br>    ├── echo/<br>    │   ├── config.yaml<br>    │   ├── spec.yaml<br>    │   ├── patches.yaml<br>    │   ├── request-termination.yaml<br>    │   ├── echo.yaml<br>    │   └── echo.sh<br>    │<br>    ├── httpbin/<br>    │   ├── config.yaml<br>    │   ├── example.yaml<br>    │   └── example.sh<br>    │<br>    ├── scripts/<br>    │   └── sync/<br>    │       ├── config.yaml<br>    │       ├── kong_connect.sh<br>    │       ├── routing.deck.yaml<br>    │       └── backup.yaml<br>    │<br>    └── shared/<br>        ├── self_signed_certificate.sh<br>        ├── logs/<br>        │   ├── proxy_access.log<br>        │   ├── proxy_error.log<br>        │   ├── status_access.log<br>        │   └── status_error.log<br>        │<br>        └── ssl/<br>            ├── server.crt<br>            ├── server.key<br>            ├── cluster.crt<br>            └── cluster.key</pre><h4><strong>Executing the Bash Script</strong></h4><p>The decK workflow in <em>example.sh</em> follows a safe and repeatable sequence. First, <em>deck</em> <em>gateway</em> <em>diff</em> performs a <strong>dry run</strong> and shows what would change if <em>example.yaml</em> were applied to the current state of the Kong Konnect <em>Routing</em> Control Plane. Next, <em>deck gateway validate</em> checks that the declarative file is syntactically and structurally correct before any change is made. The actual onboarding is then performed by <em>deck gateway apply</em>, which adds the <em>example-service</em>, its Expressions-based routes, and the request-termination plugin into the live Control Plane. Immediately after the apply step, <em>deck gateway dump</em> exports the full live state of the Control Plane into <em>..</em><em>/scripts/sync/backup.yaml</em>. This backup file captures not only the entities introduced by onboarding the <strong>HTTPBin API</strong> service, but also any other existing live entities already present in the Control Plane. The script then validates <em>backup.yaml</em> and runs a final <em>deck</em> <em>gateway</em> <em>diff</em> against it. When the summary reports zero entities created, updated, and deleted, it confirms that the local <em>backup.yaml</em> file exactly matches the current live Kong Konnect Routing Control Plane state. That is why the <em>backup.yaml</em> file in the <em>/scripts/sync</em> directory becomes the single source of truth for the live current configuration state of the Kong Konnect Routing Control Plane.</p><p>From the <em>KongRouting</em> project root, execute the <em>example.sh</em> bash script with <em>KongRouting</em> set as the current working directory in your terminal.</p><figure><img alt="Onboarding Kong HTTPBin API into Kong Konnect Routing Control Plane by executing the example.sh bash file." src="https://cdn-images-1.medium.com/max/1024/1*WYUHPOB7fKejrh5-BqXzKg.png" /><figcaption><strong>Onboarding</strong> Example-Service, Routes and Plugin Configurations for <strong>Kong HTTPBin API</strong> into Kong Konnect <strong>Routing Control Plane</strong></figcaption></figure><p>The terminal output reflects each decK operation, executed by <em>example.sh</em>, and follows the same safe workflow used earlier for the Kong echo API onboarding. The first <em>deck</em> <em>gateway</em> <em>diff</em> compares the local state file <em>example.yaml</em> with the current live state of the Kong Konnect <em>Routing</em> Control Plane. Because <em>example.yaml</em> contains only the HTTPBin API configuration and does not include the certificate, SNI, or the previously onboarded Kong echo API entities already present in the Control Plane, decK reports both <strong>creates</strong> and <strong>deletes</strong> in the diff output. The create side corresponds to the four Kong entities required for <strong>HTTPBin API</strong> onboarding a Service (<em>example-service</em>), two Routes (<em>example-status-route</em> and <em>example-favicon-route</em>), and one route-level <em>request-termination</em> plugin. The delete side appears only because those already-existing resources are absent from the local <em>example.yaml</em> file during the dry-run comparison. However, when the script proceeds to <em>deck gateway apply</em>, <strong>decK</strong> performs a <strong>non-destructive</strong> <em>apply </em><strong>operation</strong> rather than a full <em>deck</em> <em>gateway</em> <em>sync</em>, so it creates only the <strong>four HTTPBin Kong entities</strong> and does <strong>not remove</strong> any existing certificate, SNI, or Kong echo API objects from the live Control Plane. After the apply step, <em>deck gateway dump</em> exports the complete current Control Plane state into <em>/scripts/sync/backup.yaml</em>. Since that backup file already exists from the earlier Kong echo API onboarding, decK <strong>prompts</strong> for confirmation <strong>before overwriting</strong> it, which is expected and desirable because the backup must now be refreshed to include both the previously existing live configuration and the newly added HTTPBin API entities. Finally, when <em>deck</em> <em>gateway</em> <em>diff </em>is run against the updated <em>backup.yaml</em>, the summary shows <strong><em>0</em> <em>Kong</em> <em>entities</em></strong> <em>to</em> <em>create,</em> <em>update,</em> <em>or</em> <em>delete</em> because the dumped backup file now <strong>exactly matches</strong> the live state of the Kong Konnect <em>Routing</em> Control Plane. That <strong><em>zero-drift</em></strong> result confirms that <em>backup.yaml</em> has been successfully refreshed and remains the <strong>single source of truth</strong> for the current live configuration state of the <em>Routing</em> Control Plane.</p><figure><img alt="Kong Gateway Service example-service created in Kong Konnect Routing Control Plane representing the HTTPBin API Upstream backend service." src="https://cdn-images-1.medium.com/max/1024/1*ogGDgkpNMHFnVxcikspljQ.png" /><figcaption>Kong Konnect Gateway services Page Showing <strong>HTTPBin API Onboarded</strong> into Kong Konnect <strong>Routing</strong> Control Plane as <strong>example-service</strong></figcaption></figure><figure><img alt="The example-service routes added into Kong Konnect Routing Control Plane based on the declarative configuration state file example.yaml of Kong HTTPBin API during the Onboarding process." src="https://cdn-images-1.medium.com/max/1024/1*5bbE2R17Yh65NmZUa_vXVg.png" /><figcaption>Kong Konnect <strong>example-service routes</strong> added to Kong Konnect <strong>Routing</strong> Control Plane while <strong>Onboarding</strong> <strong>HTTPBin API</strong></figcaption></figure><p>The routes are configured as <strong>Expressions</strong>-based routes, allowing Kong Gateway to evaluate multiple request conditions within a single Route object instead of creating a separate Route for every individual path. In this onboarding, the <em>example-status-route</em> combines the<em>/status/&lt;status_code&gt;</em> and <em>/anything</em> <strong>HTTPBin API</strong> endpoints into one Kong Route object by using the logical <em>OR</em> operator within a single route expression. API requests either matching the regular expression for valid <em>/status</em> response codes or starting with <em>/anything</em> are <strong>routed</strong> to the <strong>same upstream service</strong>, provided they arrive on destination port <em>8443</em>. This is a practical advantage of the Kong <strong>Expressions router</strong> where multiple route paths belonging to the same service and sharing similar routing conditions can be consolidated into a single Kong Route object, reducing configuration sprawl, simplifying operational management, and improving route evaluation efficiency. In large-scale Kong Konnect deployments, fewer Route objects mean lower configuration complexity and better overall routing performance across the Kong Konnect API platform.</p><figure><img alt="Request-Termination Plugin added to example-favicon-route of example-service in Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*ePhxGD5KfKwKhbT2Xgfelg.png" /><figcaption>The <strong>Request-Termination</strong> Plugin Added to the <strong>example-favicon-route</strong> of <strong>example-service Onboarded</strong> into Kong Konnect <strong>Routing </strong>Control Plane</figcaption></figure><p>The <em>request-termination</em> plugin attached to <em>example-favicon-route</em> ensures that automatic browser requests to<em>/favicon.ico </em>on port <em>8443</em> are handled directly at the Kong Gateway layer instead of being forwarded to the HTTPBin upstream service. This prevents unnecessary backend calls, reduces noise in upstream traffic, and keeps the service focused only on meaningful API requests such as <em>/status/&lt;code&gt;</em> and <em>/anything</em>. With this, the <strong>onboarding</strong> of the <strong>HTTPBin API</strong> <em>service</em> into the Kong Konnect <em>Routing</em> Control Plane is complete. The <em>example-service</em>, its <strong>Expressions</strong>-based routes, and the <em>request-termination</em> plugin are now live, <strong>declaratively</strong> managed, and <strong>propagated</strong> to the connected Kong Gateway Data Plane, ready to demonstrate precise destination-port-based traffic filtering in the validation steps that follow.</p><p>Next, in <a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-83a4cef197ee"><strong>Part-4</strong></a> of this blog series, we will validate <strong>Expressions-based</strong> <strong>routing policies</strong> in Kong Gateway to <strong>filter</strong> <strong>inbound API</strong> requests by destination port number, <strong>verify request flow</strong> behavior across multiple Gateway listener ports, and analyze how Kong Expressions Routing improves route matching flexibility and operational control within the Kong Konnect-managed self-managed Gateway environment. Additionally, we will <strong>implement</strong> an <strong>automated backup</strong> and <strong>controlled reconciliation</strong> workflow to <strong>safely synchronize</strong> the Kong Konnect Routing Control Plane with the local backup.yaml declarative configuration state, ensuring that the declarative configuration remains the single source of truth for the live Routing Control Plane.</p><h4>Blog Series — <a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-83a4cef197ee">Part-4</a>:</h4><p><em>Validating API Traffic Flow Across Multiple Kong Gateway Destination Ports with Backup Reconciliation Workflows</em></p><p><a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-83a4cef197ee">Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port…</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=611822f26fc2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port…]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-dde0a6af8c13?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/dde0a6af8c13</guid>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[docker]]></category>
            <category><![CDATA[docker-compose]]></category>
            <category><![CDATA[kong-konnect]]></category>
            <category><![CDATA[bash]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Sun, 10 May 2026 12:05:14 GMT</pubDate>
            <atom:updated>2026-05-11T13:01:55.612Z</atom:updated>
            <cc:license>https://creativecommons.org/licenses/by-nc-nd/4.0/</cc:license>
            <content:encoded><![CDATA[<h3>Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port Number — Part-2</h3><figure><img alt="Technical banner illustration showing Kong Gateway Expressions Routing filtering inbound API requests by destination port number." src="https://cdn-images-1.medium.com/max/1024/1*f4IAE4OPC47sP_dPpKUsFA.png" /><figcaption>Kong Gateway Enterprise filtering inbound API requests by Destination Port Number</figcaption></figure><p>Shubhojit Dasgupta — Independent API Architect</p><p><a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-number-9c23e4908c26"><strong>Part-1</strong></a> of this blog series established the foundational architecture and configuration required for implementing expressions-based routing in Kong Gateway. We explored the inbound API traffic flow, reviewed the fundamentals of Kong Expressions syntax, examined the overall solution architecture, and configured the Kong Konnect API Platform along with the Personal Access Token required for secure Control Plane management.</p><p>In this part of the blog, we will provision the Kong Konnect Control Plane with a self-managed Kong Gateway Data Plane, install and configure the self-managed Kong Gateway runtime, generate a self-signed TLS certificate and upload it into the Kong Konnect Platform, and finally validate the operational behavior of the Kong Gateway Proxy and Status API endpoints.</p><h3>Provision Kong Konnect Control Plane with Self-Managed Kong Gateway</h3><p>To create a new Control Plane in Kong Konnect along with an associated Kong Gateway instance, navigate to the <strong>Gateway Manager</strong> by selecting <strong>API Gateway → Gateways</strong> from the left-hand navigation pane.</p><p>Click on the <strong>“New gateway”</strong> button to initiate the setup. Configure Konnect Control Plane with the name <strong>“Routing”</strong> and assign a label using the key-value pair:</p><pre>created-for: expressions-routing</pre><p>Provide a meaningful description for the Kong Konnect Control Plane, such as <strong>“Implementing Expressions Router Solution in Kong Gateway.”</strong></p><figure><img alt="Provision a new Kong Konnect Control Plane and Gateway Data Plane." src="https://cdn-images-1.medium.com/max/1024/1*Ex6Em9qZ1FXmgAUqUP-2_w.png" /><figcaption>Create new Gateway Control Plane</figcaption></figure><p>Clicking the <strong>“New gateway”</strong> button launches the <strong>Create API gateway modal dialog</strong>, enabling one to configure the Control Plane and determine the provisioning model for the associated Kong Gateway instance in Kong Konnect.</p><figure><img alt="Create API gateway modal dialog for provisioning the Konnect Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*Quk0_WBA8JE67gzPUeNlcg.png" /><figcaption>Create API gateway Modal Dialog</figcaption></figure><p>In the “<em>Create API gateway</em>” modal dialog the Gateway name and Gateway description are Control Plane name and Control Plane description respectively. In this blog Kong is installed as a self-managed gateway running in a docker container. So, for the setup “Where do you want to run your gateway?” choose “Self-managed”. This will allow the Kong Gateway runtime to be installed anywhere even in a local computer connected to Kong Konnect Control Plane hosted in <strong>India (Mumbai / ap-south-1) </strong>region of AWS cloud, as selected during Kong Konnect Organization creation.</p><h4>Install Self-Managed Kong Gateway Data Plane Node</h4><p>Select “<strong>Create</strong>” button to provision the configured Konnect Control Plane setup. The “<strong>Create a data plane node</strong>” modal dialog opens where one selects the version of the Kong Gateway as “<strong>Self-Managed Gateway 3.14</strong>” and for the platform where Kong Gateway shall be deployed select the drop down option “<strong>Mac (docker)</strong>”. In this blog Kong gateway is installed running as a docker container in Mac. One can select the operating system of their choice from the dropdown menu to implement the routing solution described in this blog. However, ensure that Docker Desktop is installed and properly configured on the machine before proceeding.</p><figure><img alt="Create a Data Plane Modal Dialog to setup and run Kong Gateway runtime node." src="https://cdn-images-1.medium.com/max/1024/1*uRdY5ruWvW7I2P6X8iEJVw.png" /><figcaption>Create a data plane node Modal Dialog in Kong Konnect UI</figcaption></figure><p>Select the <strong>“<em>Generate certificate and script</em>”</strong> option to automatically generate the required certificates and Docker run commands based on the official Kong Gateway Docker image. These commands can be used to provision the Data Plane node and establish connectivity with Kong Konnect.</p><p>Alternatively, one can also choose the <strong>“Set up later”</strong> option to create only the Konnect Control Plane and defer the Data Plane provisioning to a later stage.</p><p>Copy the environment variable values from the generated Docker run script and store them in the <em>.env </em>file, mapping each value to its corresponding environment variable key. This approach helps centralize configuration and simplifies container deployment.</p><p><strong>Adding the Kong Gateway Script and Environment Settings</strong></p><figure><img alt="Generating Kong Gateway Data Plane Node Scripts to Create the Kong Gateway Docker Compose Specification." src="https://cdn-images-1.medium.com/max/1024/1*sTHspauUiyVFSWn4L8uaMA.png" /><figcaption>Generating Kong Gateway Data Plane Node Scripts in Kong Konnect UI</figcaption></figure><p>Copy the value for environment KONG_CLUSTER_CERT starting from — — -BEGIN CERTIFICATE — — - till the — — -END CERTIFICATE — — - from the script generated above into the <em>cluster.crt</em> file created earlier under <em>/ssl</em> folder.</p><p>Copy the value for environment KONG_CLUSTER_CERT_KEY starting from — — BEGIN PRIVATE KEY — — - till the — — -END PRIVATE KEY — — - from the script into the <em>cluster.key</em> file created earlier under <em>/ssl </em>folder.</p><p>The <em>cluster.crt</em> file will contain the following content:</p><pre>-----BEGIN CERTIFICATE-----<br>MIICBjCCAaygAwIBAgIBATAKBggqhkjOPQQDBDA0MTIwCQYDVQQGEwJJTjAlBgNV<br>BAMeHgBrAG8AbgBuAGUAYwB0AC0AUgBvAHUAdABpAG4AZzAeFw0yNjA1MDUwNzAz<br>MzNaFw0zNjA1MDUwNzAzMzNaMDQxMjAJBgNVBAYTAklOMCUGA1UEAx4eAGsAbwBu<br>AG4AZQBjAHQALQBSAG8AdQB0AGkAbgBnMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD<br>QgAEl5FP6/tB2//ZxdLgDNDN2kGfjSN2geQ8ARVD9jLfoDZUAJ1zMPYv6+//ibCk<br>6PIH5GZVJKT/cZ4tb8SZ7e18ZqOBrjCBqzAMBgNVHRMBAf8EAjAAMAsGA1UdDwQE<br>AwIABjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwFwYJKwYBBAGCNxQC<br>BAoMCGNlcnRUeXBlMCMGCSsGAQQBgjcVAgQWBBQBAQEBAQEBAQEBAQEBAQEBAQEB<br>ATAcBgkrBgEEAYI3FQcEDzANBgUpAQEBAQIBCgIBFDATBgkrBgEEAYI3FQEEBgIE<br>ABQACjAKBggqhkjOPQQDBANIADBFAiBGqEzVV8ZBZ/pCN4WYDdaoVlAXz9BizaJg<br>0LEvOG27AAIhALOhzxUegCC0zMYDj6clC2bV/Zve9Kh9i5qQQT6m6r5J<br>-----END CERTIFICATE-----</pre><p>The <em>cluster.key</em> file will contain the following content:</p><pre>-----BEGIN PRIVATE KEY-----<br>MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQgX3U2ZmOiETBJZaEx<br>ZaqVYWp/7iCfnjXHGPLv+NCLMpKgCgYIKoZIzj0DAQehRANCAASXkU/r+0Hb/9nF<br>0uAM0M3aQZ+NI3aB5DwBFUP2Mt+gNlQAnXMw9i/r7/+JsKTo8gfkZlUkpP9xni1v<br>xJnt7Xxm<br>-----END PRIVATE KEY-----</pre><p>Copy the values for the following environment variables from the script generated:</p><p>· KONG_CLUSTER_CONTROL_PLANE</p><p>· KONG_CLUSTER_SERVER_NAME</p><p>· KONG_CLUSTER_TELEMETRY_ENDPOINT</p><p>· KONG_CLUSTER_TELEMETRY_SERVER_NAME</p><p>The environment variable and the certificates need to be updated every time a new Konnect Control Plane is created.</p><p>Add the above environment variable values from the script into the .<em>env</em> file under the root project <em>KongRouting</em> folder, mapped to the corresponding environment keys:</p><p>· KONG_CP_ENDPOINT</p><p>· KONG_CP_SERVER_NAME</p><p>· KONG_TELEMETRY_ENDPOINT</p><p>· KONG_TELEMETRY_SERVER_NAME</p><p>To <strong>operationalize</strong> Expressions Router solution, a self-managed Data Plane node of Kong Gateway must be provisioned and securely connected to the Kong Konnect Control Plane. In this setup, <strong>Docker Compose</strong> is used as the <strong>orchestration layer</strong> to declaratively define and run the Kong container with all required runtime configurations.</p><p>This approach provides:</p><p>· <strong>Environment consistency</strong> through declarative configuration</p><p>· <strong>Portability</strong> across local development environments</p><p>· <strong>Separation of concerns</strong> between configuration (<em>.env</em>) and deployment (<em>docker-compose.yaml</em>)</p><p>The setup is broken down into three key steps:</p><p>1. Defining environment variables using a <em>.env</em> file</p><p>2. Referencing these variables within the Docker Compose specification</p><p>3. Bootstrapping and validating the Data Plane connection to Konnect</p><h4><strong>Adding the .env File</strong></h4><p>The <em>.env</em> file serves as the <strong>central configuration artifact</strong> for the Docker Compose-based deployment. It defines all runtime parameters required to initialize and run the Kong Gateway container in Data Plane mode.</p><p>Each entry in the <em>.env</em> file follows a <strong>key-value pair structure</strong>, where:</p><p>· The <strong>key</strong> represents the configuration parameter expected by Kong or Docker Compose</p><p>· The <strong>value</strong> is derived from:</p><p>→ The <strong>generated script</strong> in Kong Konnect (for Control Plane connectivity)</p><p>→ <strong>Local environment decisions</strong> (e.g., ports, volumes, container naming)</p><p><strong>→ Security artifacts</strong> (e.g., certificate paths)</p><p><strong>Key Configuration Settings:</strong></p><p>· <strong>Container &amp; Runtime Settings</strong> — Define container identity and lifecycle behavior:</p><p>→ KONG_CONTAINER_NAME, KONG_HOST_NAME, KONG_RESTART</p><p>· <strong>Networking &amp; Ports</strong> — Control how traffic is exposed:</p><p>→ KONG_PROXY_PORT, KONG_PROXY_SECURED_PORT1, KONG_STATUS_PORT</p><p>· <strong>Konnect Control Plane Connectivity</strong> — These values are <strong>directly sourced from the generated script</strong>:</p><p>→ KONG_CP_ENDPOINT, KONG_CP_SERVER_NAME</p><p>→ KONG_TELEMETRY_ENDPOINT, KONG_TELEMETRY_SERVER_NAME</p><p>· <strong>Security &amp; mTLS Configuration</strong> — Required for secure clustering between Data Plane and Control Plane:</p><p>→ KONG_CLUSTER_MTLS=pki</p><p>→ Certificate paths mapped via mounted volumes</p><p>· <strong>Routing Behavior</strong> — Enables Expressions-based routing:</p><p>→ KONG_ROUTER_FLAVOR=expressions</p><p>· <strong>Mode Configuration</strong> — Defines Data Plane operation:</p><p>→ KONG_ROLE=data_plane</p><p>→ KONG_DATABASE=off</p><p>→ KONG_KONNECT_MODE=on</p><p>· <strong>Observability &amp; Logging</strong> — Configures log persistence:</p><p>→ Volume mappings (KONG_LOGS_VOLUME, etc.)</p><p>→ Log file paths inside the container</p><p>This design ensures that <strong>all configuration is externalized</strong>, making the deployment reproducible and easier to manage across environments. The <em>.env</em> file will contain the following environment variable key/value pairs:</p><pre># Kong configurations<br>KONG_VERSION=3.14.0.1<br>NETWORK=kong-edu-net<br>KONG_CONTAINER_NAME=kong-routing<br>KONG_HOST_NAME=kong-routing<br>KONG_RESTART=on-failure<br>KONG_PROXY_PORT=8000<br>KONG_PROXY_SECURED_PORT1=8443<br>KONG_PROXY_SECURED_PORT2=443<br>KONG_STATUS_PORT=8101<br>KONG_LOGS_VOLUME=./kong/shared/logs<br>KONG_DOCKER_LOGS_VOLUME=/srv/shared/logs<br>KONG_CERT_VOLUME=./kong/shared/ssl<br>KONG_DOCKER_CERT_VOLUME=/srv/shared/ssl<br>KONG_ROLE=data_plane<br>KONG_DATABASE=off<br>KONG_VITALS=off<br>KONG_UPSTREAM_HOST=host.docker.internal<br>KONG_CP_ENDPOINT=ec8ad6cb89.in.cp.konghq.com:443<br>KONG_CP_SERVER_NAME= ec8ad6cb89.in.cp.konghq.com<br>KONG_TELEMETRY_ENDPOINT= ec8ad6cb89.in.tp.konghq.com:443<br>KONG_TELEMETRY_SERVER_NAME= ec8ad6cb89.in.tp.konghq.com<br>KONG_CLUSTER_MTLS=pki<br>KONG_LUA_SSL=system<br>KONG_UNTRUSTED_LUA=sandbox<br>KONG_PROXY_LISTEN=0.0.0.0:8000, 0.0.0.0:8443 http2 ssl, 0.0.0.0:443 http2 ssl<br>KONG_STATUS_LISTEN=0.0.0.0:8101 http2 ssl<br>KONG_NGINX_WORKER_PROCESSES=1<br>KONG_KONNECT_MODE=on<br>KONG_DP_LABLES=created-for:routing,type:docker-MacOSArm<br>KONG_ROUTER_FLAVOR=expressions<br>KONG_DEBUG_HEADER=on<br>KONG_INTERVAL=30s<br>KONG_TIMEOUT=30s<br>KONG_RETRIES=3</pre><p>The value for the environment <em>Kong_DP_LABELS</em> should match the label added in the “<strong>Create a data plane node</strong>” modal dialog under the “<em>Add Labels</em>” section. It expects a key: value pair. These labels provide metadata to identify Kong Data Plane nodes running, connected and synchronized with the Kong Konnect Control Plane.</p><figure><img alt="Adding Kong Data Plane Labels." src="https://cdn-images-1.medium.com/max/1024/1*DqsoGUmy3XJ4IPrUxfuMog.png" /><figcaption>Add Data Plane Labels</figcaption></figure><h3>Configuring Kong Gateway Data Plane Node</h3><p>In this blog we are using Kong Gateway Docker Image with gateway version <strong>3.14.0.1</strong> as specified in the <em>.env</em> file by the environment key/value pair:</p><pre>KONG_VERSION=3.14.0.1</pre><p>With the <em>.env</em> file in place, the <em>docker-compose.yaml</em> file defines the <strong>container topology and runtime behavior</strong> of the Kong Data Plane node.</p><p>The key concept here is <strong>environment variable interpolation</strong>. Docker Compose uses the <em>${VARIABLE_NAME}</em> syntax to dynamically substitute values from the <em>.env</em> file into the service definition.</p><h4><strong>Network Definition</strong></h4><p>The <em>networks</em> section defines a custom bridge network used for container communication. In this setup, a network named <em>kong-edu-net</em> is declared, with its actual name dynamically resolved using the <em>${NETWORK</em>} variable from the <em>.env</em> file.</p><pre>networks:<br>  kong-edu-net:<br>    name: ${NETWORK}<br>    driver: bridge</pre><p>The <em>bridge</em> driver enables isolated, internal networking between containers running on the same host. By externalizing the network name through the <em>.env</em> file, the configuration remains flexible and environment-agnostic, allowing the same Docker Compose definition to be reused across different setups without modification.</p><p>This network is then referenced by the kong-dp service to ensure that the Kong Gateway Data Plane container can communicate reliably within the defined container ecosystem.</p><pre>kong-dp:<br>    networks:<br>    - ${NETWORK}<br>   container_name: &quot;${KONG_CONTAINER_NAME}&quot;<br>   hostname: &quot;${KONG_HOST_NAME}&quot;</pre><p>The kong-dp service is explicitly attached to the custom bridge network defined earlier using the <em>${NETWORK</em>} variable, ensuring that the container participates in the same isolated network namespace. The <em>networks</em> attribute associates the service with the dynamically resolved network from the <em>.env</em> file, enabling consistent inter-container communication.</p><p>The <em>container_name</em> parameter assigns a deterministic name to the container, simplifying container management and debugging operations (e.g., <em>docker</em> <em>logs</em>, <em>docker</em> <em>exec</em>).</p><p>The <em>hostname</em> defines the internal DNS name of the container within the network, which can be used for <strong>service-to-service communication</strong> if additional containers are introduced into the same network.</p><p>Together, these configurations ensure that the Kong Gateway Data Plane container is properly networked, identifiable, and accessible within the Docker environment.</p><h4><strong>Volume Mounting &amp; Kong Gateway Container Health Check</strong></h4><p>The <em>volumes</em> configuration enables persistent storage by mapping host directories to paths inside the container. In this setup, log files and TLS certificates required by the Kong Gateway Data Plane node are externalized to the host system:</p><pre>volumes:<br>  - ${KONG_LOGS_VOLUME}:${KONG_DOCKER_LOGS_VOLUME}<br>  - ${KONG_CERT_VOLUME}:${KONG_DOCKER_CERT_VOLUME}</pre><p>The first mapping ensures that Kong access and error logs are persisted outside the container, making them available for debugging and observability even if the container is restarted or recreated. The second mapping provides the container with access to <strong>SSL/TLS</strong> certificates required for secure communication, including mTLS with the Control Plane.</p><p>The <em>healthcheck</em> directive defines a container-level health probe:</p><pre>healthcheck:<br>   test: [&quot;CMD&quot;, &quot;kong&quot;, &quot;health&quot;]<br>   interval: ${KONG_INTERVAL}<br>   timeout: ${KONG_TIMEOUT}<br>   retries: ${KONG_RETRIES}</pre><p>This periodically executes the <em>kong</em> <em>health</em> command inside the container to verify that the runtime is operational. The interval, timeout, and retry values are dynamically injected from the <em>.env</em> file, allowing fine-grained control over health monitoring behavior.</p><p>Finally, the restart policy ensures resilience:</p><pre>restart: ${KONG_RESTART}</pre><p>With <em>on-failure</em> (as defined in the <em>.env</em>), the container is automatically restarted if it exits due to an error, improving overall system reliability. Together, these configurations provide <strong>persistent storage, secure certificate management, runtime health validation, and fault tolerance</strong> for the Kong Gateway Data Plane container.</p><h4><strong>Port Mapping</strong></h4><p>The <em>ports</em> section defines how container ports are exposed to the host system, enabling external access to the Kong Gateway Data Plane services.</p><pre>ports:<br> - &quot;${KONG_PROXY_PORT}:8000/tcp&quot;<br> - &quot;${KONG_STATUS_PORT}:8101/tcp&quot;<br> - &quot;${KONG_PROXY_SECURED_PORT1}:8443/tcp&quot;<br> - &quot;${KONG_PROXY_SECURED_PORT2}:443/tcp&quot;</pre><p>Each entry follows the format: <em>&lt;host_port&gt;:&lt;container_port&gt;/&lt;protocol&gt;</em></p><p>Environment values are dynamically injected from the <em>.env</em> file using variable interpolation.</p><p><strong>Port Breakdown:</strong></p><p>· <strong>Proxy (HTTP — Default Port) </strong>— ${KONG_PROXY_PORT}:8000</p><p>Exposes the primary HTTP proxy endpoint used for routing incoming client requests.</p><p>· <strong>Status API</strong> — ${KONG_STATUS_PORT}:8101</p><p>Exposes the status endpoint for health checks and runtime monitoring of the Kong instance.</p><p>· <strong>Proxy (HTTPS — Default Port)</strong> — ${KONG_PROXY_SECURED_PORT1}:8443</p><p>Enables secure HTTPS traffic over a configurable port (commonly used for development or non-standard setups).</p><p>· <strong>Proxy (HTTPS — Standard Port)</strong> — ${KONG_PROXY_SECURED_PORT2}:443</p><p>Maps the container’s HTTPS endpoint to the standard TLS port, allowing clients to access services without specifying a custom port.</p><p>By externalizing these port values in the <em>.env</em> file, the configuration remains flexible and can be adapted to different environments without modifying the Docker Compose definition. In this setup, the Kong Gateway Data Plane is configured with <strong>two TLS-enabled proxy listeners</strong>, allowing it to accept HTTPS requests on both the <strong>standard port (443)</strong> and a Kong <strong>default secure port (8443)</strong>. This dual-port configuration is essential for implementing <strong>Expressions-based routing</strong>, where incoming requests can be filtered and routed based on the <strong>destination port number</strong>. This setup ensures that the Kong Gateway Data Plane node is accessible over both HTTP and HTTPS, while also exposing operational endpoints for observability and health monitoring.</p><h4><strong>Environment Section with Important Configuration Properties</strong></h4><p>The <em>environment</em> section defines the runtime configuration of the Kong Gateway Data Plane container. These variables are injected at startup via Docker Compose using values sourced from the <em>.env</em> file.</p><pre>environment:<br>  UPSTREAM_HOST: ${KONG_UPSTREAM_HOST}<br>  KONG_CLUSTER_CONTROL_PLANE: &quot;${KONG_CP_ENDPOINT}&quot;<br>  KONG_CLUSTER_SERVER_NAME: &quot;${KONG_CP_SERVER_NAME}&quot;<br>  KONG_CLUSTER_TELEMETRY_ENDPOINT: &quot;${KONG_TELEMETRY_ENDPOINT}&quot;<br>  KONG_CLUSTER_TELEMETRY_SERVER_NAME: &quot;${KONG_TELEMETRY_SERVER_NAME}&quot;<br>  KONG_CLUSTER_MTLS: &quot;${KONG_CLUSTER_MTLS}&quot;<br>  KONG_CLUSTER_CERT: &quot;${KONG_DOCKER_CERT_VOLUME}/cluster.crt&quot;<br>  KONG_CLUSTER_CERT_KEY: &quot;${KONG_DOCKER_CERT_VOLUME}/cluster.key&quot;<br>  KONG_PROXY_LISTEN: &quot;${KONG_PROXY_LISTEN}&quot;<br>  KONG_STATUS_LISTEN: &quot;${KONG_STATUS_LISTEN}&quot;<br>  KONG_SSL_CERT_KEY: &quot;${KONG_DOCKER_CERT_VOLUME}/server.key&quot;<br>  KONG_SSL_CERT: &quot;${KONG_DOCKER_CERT_VOLUME}/server.crt&quot;<br>  KONG_STATUS_SSL_CERT_KEY: &quot;${KONG_DOCKER_CERT_VOLUME}/server.key&quot;<br>  KONG_STATUS_SSL_CERT: &quot;${KONG_DOCKER_CERT_VOLUME}/server.crt&quot;<br>  KONG_ROUTER_FLAVOR: &quot;${KONG_ROUTER_FLAVOR}&quot;<br>  KONG_PROXY_ACCESS_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/proxy_access.log&quot;<br>  KONG_PROXY_ERROR_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/proxy_error.log&quot;<br>  KONG_STATUS_ACCESS_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/status_access.log&quot;<br>  KONG_STATUS_ERROR_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/status_error.log&quot;</pre><p><strong>Key Responsibilities of this Configuration:</strong></p><p>· <strong>Control Plane Connectivity</strong>: Parameters such as <em>KONG_CLUSTER_CONTROL_PLANE</em>, <em>KONG_CLUSTER_SERVER_NAME</em>, and telemetry endpoints establish secure communication with Kong Konnect.</p><p>· <strong>mTLS Security Setup</strong>: <em>KONG_CLUSTER_CERT</em> and <em>KONG_CLUSTER_CERT_KEY </em>define the client certificate pair used for <strong>mutual TLS</strong> <strong>authentication</strong> between the Data Plane and Control Plane.</p><p>· <strong>TLS Listener Configuration</strong>: <em>KONG_PROXY_LISTEN</em> and <em>KONG_STATUS_LISTEN</em> configure HTTPS-enabled listeners for both proxy traffic and the status endpoint.</p><p>· <strong>Expressions Routing Enablement</strong>: <em>KONG_ROUTER_FLAVOR=expressions</em> activates the <em>Expressions</em> router, which is central to implementing port-based API request filtering.</p><p>· <strong>Logging Configuration</strong>: Log file paths are explicitly defined to ensure structured logging for both proxy and status endpoints.</p><p>· <strong>Proxy TLS Certificate (Private Key)</strong>: <em>KONG_SSL_CERT_KEY</em> points Kong’s HTTPS <em>proxy</em> <em>listeners</em> (ports 443/8443) to server private key file (<em>server.key</em>) mounted inside the container at <em>${KONG_DOCKER_CERT_VOLUME}</em>, enabling <strong>TLS termination</strong> for inbound API traffic.</p><p>· <strong>Proxy TLS Certificate (Public Cert)</strong>: <em>KONG_SSL_CERT</em> specifies the server certificate file (<em>server.crt</em>) presented to clients connecting to the HTTPS proxy listeners; together with <em>KONG_SSL_CERT_KEY</em>, it completes the cert/key pair used to establish encrypted client connections.</p><p>· <strong>Status API TLS Certificate (Private Key)</strong>: <em>KONG_STATUS_SSL_CERT_KEY</em> points the <strong>TLS-enabled Status API</strong> listener (for example, <strong>port 8101</strong> when configured with <strong><em>ssl</em></strong>) to the same private key (<em>server.key</em>) so health and readiness endpoints can be served over HTTPS.</p><p>· <strong>Status API TLS Certificate (Public Cert)</strong>: <em>KONG_STATUS_SSL_CERT</em> provides the certificate (<em>server.crt</em>) that the Status API presents during the <strong>TLS handshake</strong>; using the same cert/key pair as the proxy keeps <em>localhost </em>HTTPS behavior consistent across both <strong>proxy</strong> and <strong>status</strong> endpoints.</p><p><strong>Note:</strong> The proxy and status endpoints can share the same certificate/key pair because they terminate TLS on the same Kong Gateway container for the same hostname (e.g., <em>localhost</em>), just on different listener ports.</p><p><strong>Log and Certificate Propagation to Host:</strong></p><p>Logs and certificates generated or consumed by Kong Gateway container are <strong>persisted on the host machine</strong> through Docker volume mappings defined earlier:</p><p>· Logs are written to: <em>./kong/shared/logs</em></p><p>· Certificates are read from and maintained in: <em>./kong/shared/ssl</em></p><p>These host paths are mounted into the container as:</p><p>· ${KONG_DOCKER_LOGS_VOLUME} → <em>/srv/shared/logs</em></p><p>· ${KONG_DOCKER_CERT_VOLUME} → <em>/srv/shared/ssl</em></p><p>Because of this mapping:</p><p>· Any logs generated inside the container (e.g., <em>proxy_access.log</em>, <em>proxy_error.log</em>) are <strong>automatically written to the host filesystem</strong></p><p>· TLS certificates (cluster and server certificates) stored in the host <em>/ssl</em> directory are <strong>directly consumed by the container at runtime</strong></p><p>This ensures:</p><ul><li><strong>Persistence</strong> beyond container lifecycle</li><li><strong>Traceability</strong> for debugging and monitoring</li><li><strong>Seamless certificate management</strong> without rebuilding the container</li></ul><p>The container does not need explicit awareness of host paths. Docker handles the synchronization transparently through the defined volume bindings.</p><p>The <em>docker-compose.yaml</em> file in this project defines the complete containerized setup for running the Kong Gateway Data Plane node. It declaratively specifies the network configuration, container properties, volume mappings, port exposure, and environment variables required to establish secure communication with Kong Konnect Control Plane.</p><p>The configuration also leverages <strong>environment variable interpolation</strong> using the <em>.env</em> file, ensuring that all runtime parameters are externalized and can be easily modified without altering the core Docker Compose definition.</p><p>The file content is as follows:</p><pre>networks:<br>  kong-edu-net:<br>    name: ${NETWORK}<br>    driver: bridge<br><br>services:<br>  ######################################################<br>  ########  Kong Data Plane Self-Managed  ##############<br>  ######################################################<br>  kong-dp:<br>    networks:<br>    - ${NETWORK}<br>    image: kong/kong-gateway:${KONG_VERSION}<br>    container_name: &quot;${KONG_CONTAINER_NAME}&quot;<br>    hostname: &quot;${KONG_HOST_NAME}&quot;<br>    volumes:<br>    - ${KONG_LOGS_VOLUME}:${KONG_DOCKER_LOGS_VOLUME}<br>    - ${KONG_CERT_VOLUME}:${KONG_DOCKER_CERT_VOLUME}<br>    healthcheck:<br>      test: [&quot;CMD&quot;, &quot;kong&quot;, &quot;health&quot;]<br>      interval: ${KONG_INTERVAL}<br>      timeout: ${KONG_TIMEOUT}<br>      retries: ${KONG_RETRIES}<br>    restart: ${KONG_RESTART}<br>    ports:<br>    - &quot;${KONG_PROXY_PORT}:8000/tcp&quot;<br>    - &quot;${KONG_STATUS_PORT}:8101/tcp&quot;<br>    - &quot;${KONG_PROXY_SECURED_PORT1}:8443/tcp&quot;<br>    - &quot;${KONG_PROXY_SECURED_PORT2}:443/tcp&quot;<br>    environment:<br>      KONG_ROLE: &quot;${KONG_ROLE}&quot;<br>      KONG_DATABASE: &quot;${KONG_DATABASE}&quot;<br>      KONG_VITALS: &quot;${KONG_VITALS}&quot;<br>      UPSTREAM_HOST: ${KONG_UPSTREAM_HOST}<br>      KONG_CLUSTER_CONTROL_PLANE: &quot;${KONG_CP_ENDPOINT}&quot;<br>      KONG_CLUSTER_SERVER_NAME: &quot;${KONG_CP_SERVER_NAME}&quot;<br>      KONG_CLUSTER_TELEMETRY_ENDPOINT: &quot;${KONG_TELEMETRY_ENDPOINT}&quot;<br>      KONG_CLUSTER_TELEMETRY_SERVER_NAME: &quot;${KONG_TELEMETRY_SERVER_NAME}&quot;<br>      KONG_CLUSTER_MTLS: &quot;${KONG_CLUSTER_MTLS}&quot;<br>      KONG_CLUSTER_CERT: &quot;${KONG_DOCKER_CERT_VOLUME}/cluster.crt&quot;<br>      KONG_CLUSTER_CERT_KEY: &quot;${KONG_DOCKER_CERT_VOLUME}/cluster.key&quot;<br>      KONG_LUA_SSL_TRUSTED_CERTIFICATE: &quot;${KONG_LUA_SSL}&quot;<br>      KONG_UNTRUSTED_LUA: &quot;${KONG_UNTRUSTED_LUA}&quot;<br>      KONG_PROXY_LISTEN: &quot;${KONG_PROXY_LISTEN}&quot;<br>      KONG_STATUS_LISTEN: &quot;${KONG_STATUS_LISTEN}&quot;<br>      KONG_SSL_CERT_KEY: &quot;${KONG_DOCKER_CERT_VOLUME}/server.key&quot;<br>      KONG_SSL_CERT: &quot;${KONG_DOCKER_CERT_VOLUME}/server.crt&quot;<br>      KONG_STATUS_SSL_CERT_KEY: &quot;${KONG_DOCKER_CERT_VOLUME}/server.key&quot;<br>      KONG_STATUS_SSL_CERT: &quot;${KONG_DOCKER_CERT_VOLUME}/server.crt&quot;<br>      KONG_NGINX_WORKER_PROCESSES: ${KONG_NGINX_WORKER_PROCESSES}<br>      KONG_KONNECT_MODE: &quot;${KONG_KONNECT_MODE}&quot;<br>      KONG_CLUSTER_DP_LABELS: &quot;${KONG_DP_LABLES}&quot;<br>      KONG_ROUTER_FLAVOR: &quot;${KONG_ROUTER_FLAVOR}&quot;<br>      KONG_PROXY_ACCESS_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/proxy_access.log&quot;<br>      KONG_PROXY_ERROR_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/proxy_error.log&quot;<br>      KONG_STATUS_ACCESS_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/status_access.log&quot;<br>      KONG_STATUS_ERROR_LOG: &quot;${KONG_DOCKER_LOGS_VOLUME}/status_error.log&quot;<br>      KONG_ALLOW_DEBUG_HEADER: &quot;${KONG_DEBUG_HEADER}&quot;</pre><p>The docker compose services and environment configuration settings will be executed via <em>start.sh</em> file, using bash script.</p><h4>Verify decK Communication with Konnect Control Plane</h4><p>Before starting the Data Plane container, it is important to validate connectivity with the Kong Konnect Control Plane. This ensures that authentication, endpoint configuration, and network access are correctly set up.</p><p>In this step, decK is used to perform a lightweight connectivity check using the <em>deck</em> <em>gateway</em> <em>ping</em> command. This confirms that the local environment can successfully communicate with the Control Plane before deploying the Kong Gateway Data Plane node.</p><p>The validation is driven by two artifacts:</p><p>· A <strong>configuration file (</strong><em>config.yaml</em><strong>)</strong> that defines Control Plane parameters</p><p>· A <strong>helper script (</strong><em>kong_connect.sh</em><strong>)</strong> that executes the connectivity check</p><p>This separation keeps configuration declarative and execution reusable. The configuration file <em>config.yaml </em>and bash script file <em>kong_connect.sh </em>required for this validation are organized under the <em>sync</em> folder.</p><p>The <em>kong/scripts/sync/</em> folder contains:</p><p>· The <em>routing.deck.yaml</em> → Stores the <strong>Konnect Personal Access Token</strong></p><p>· The <em>config.yaml</em> → Defines Control Plane connection parameters</p><p>· The <em>kong_connect.sh</em> → Executes the decK connectivity check</p><p>This structure ensures that <strong>authentication, configuration, and execution logic are co-located</strong>, making the setup modular and easier to manage.</p><p>The updated project folder structure with additional files will look as below:</p><pre>KongRouting/<br>├── .env<br>├── docker-compose.yaml<br>├── start.sh<br>└── kong/<br>    ├── scripts/<br>    │   └── sync/<br>    │       ├── config.yaml<br>    │       ├── kong_connect.sh<br>    │       └── routing.deck.yaml<br>    └── shared/<br>        ├── logs/<br>        │   ├── proxy_access.log<br>        │   ├── proxy_error.log<br>        │   ├── status_access.log<br>        │   └── status_error.log<br>        └── ssl/<br>            ├── server.crt<br>            ├── server.key<br>            ├── cluster.crt<br>            └── cluster.key</pre><p><strong>Configuration &amp; Execution Flow</strong></p><p>· Read Control Plane configuration dynamically using <strong><em>yq</em></strong> from <em>config.yaml</em> file. This <em>config.yaml</em> file references the file <em>routing.deck.yaml</em> containing Konnect personal access token used by <em>decK</em> for authentication and defines</p><ul><li>Control Plane Name</li><li>Konnect Control Plane API endpoint</li></ul><p>· Use the bash script in <em>kong_connect.sh</em> to read values from <em>config.yaml</em> &amp; execute <em>deck</em> <em>gateway</em> <em>ping</em> operation to validate Control Plane reachability</p><p><strong>File </strong>config.yaml:</p><pre># Control Plane Routing<br>token_file: routing.deck.yaml<br>control_plane: Routing<br>control_plane_addr: https://in.api.konghq.com</pre><p><strong>File </strong>kong_connect.sh:</p><pre>#! /usr/bin/env bash<br><br># Directory in which the deck connect script runs<br>cd kong/scripts/sync<br><br># Importing configuration variables<br>TOKEN_FILE=$(yq e &#39;.token_file&#39; ./config.yaml)<br>CONTROL_PLANE=$(yq e &#39;.control_plane&#39; ./config.yaml)<br>CONTROL_PLANE_ADDR=$(yq e &#39;.control_plane_addr&#39; ./config.yaml)<br><br># Connecting Kong Gateway runtime to Control Plane Kong_Accelerator<br>deck gateway ping \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR}<br><br># Root directory of POC<br>cd ../../../</pre><p>This design ensures all Konnect-related configuration is centralized within a single directory, avoiding fragmentation across the project.<strong> </strong>This step eliminates misconfiguration early and ensures that the Data Plane node will successfully register with Konnect once started.</p><h4>Automated Deployment of Kong Gateway Data Plane Node</h4><p>Once connectivity with the Konnect Control Plane is verified, the next step is to deploy the Kong Gateway Data Plane node using Docker Compose. This is handled through a bootstrap script (<em>start.sh</em>) located at the root of the project. The script ensures a <strong>clean deployment</strong>, starts the containerized service, and validates connectivity post-deployment.</p><p>To streamline the provisioning process, the Kong Gateway Data Plane node is deployed using an automated bootstrap bash script (<em>start.sh</em>). This script encapsulates the full deployment lifecycle ensuring a consistent and repeatable setup.</p><p>Rather than manually executing multiple commands, the script orchestrates the entire workflow using configurations defined in the files within <em>sync</em><strong> </strong>folder to verify connectivity after deployment.</p><p>· The <em>.env</em> file → Environment variables for container runtime</p><p>· The <em>docker-compose.yaml</em> file → Service Containers and Network definition</p><p>· The <em>kong/scripts/sync/config.yaml</em> → Control Plane configuration</p><p><strong>Execution Flow</strong></p><p>1. <strong>Clean Existing Containers</strong> using docker compose down — remove-orphans command</p><p>→ Removes stale containers</p><p>→ Ensures a clean deployment state</p><p>2. <strong>Start Kong Data Plane Service</strong> using docker compose up -d command</p><p>→ Launches the <em>kong-dp</em> container in detached mode</p><p>→ Applies all configurations from<em>.env</em> and <em>docker-compose.yaml</em></p><p>3. <strong>Load Control Plane Configuration</strong> via <em>CONTROL_PLANE=$(yq</em> <em>e</em> <em>‘.control_plane’ ./kong/scripts/sync/config.yaml)</em> command</p><p>→ Dynamically reads Control Plane name and API endpoint from <em>config.yaml</em></p><p>4. <strong>Validate Connectivity Post Deployment</strong> using <em>source</em> <em>kong/scripts/sync/kong_connect.sh</em> command</p><p>→ Executes decK validation script</p><p>→ Confirms runtime connectivity between Data Plane and Control Plane</p><p>This guarantees that the deployment is not just successful at the container level, but also <strong>successfully connected and synchronized</strong> with the Kong Konnect Control Plane.</p><p><strong>File</strong> start.sh:</p><pre>#! /usr/bin/env bash<br><br>docker compose down --remove-orphans<br>docker compose up -d<br><br># Source the configuration file to import environment variables<br>CONTROL_PLANE=$(yq e &#39;.control_plane&#39; ./kong/scripts/sync/config.yaml)<br><br># Checking connection between Kong Gateway runtime and Konnect Control Plane<br>printf &#39;\n&#39;<br>echo &#39;Establishing connection between Kong Gateway runtime and&#39; ${CONTROL_PLANE} &#39;Control Plane in Konnect&#39;<br><br>sleep 2<br><br>source kong/scripts/sync/kong_connect.sh</pre><p>Using a Bash-based bootstrap script makes setup highly compatible with <strong>GitOps and APIOps pipelines</strong>. The same script can be integrated into CI/CD workflows to:</p><p>· Automate provisioning of the Konnect Control Plane</p><p>· Deploy and configure the Data Plane node</p><p>· Validate connectivity as part of pipeline execution</p><p>This approach ensures that infrastructure and API gateway configuration remain <strong>version-controlled, repeatable, and environment-agnostic</strong>.</p><p>Execute bash bootstrap script (<em>start.sh</em>) via terminal with project root folder <em>KongRouting</em> as current working directory.</p><figure><img alt="Execution of the start.sh script demonstrating successful Docker Compose deployment of the Kong Gateway Data Plane node and validated connection to the Konnect Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*oWKUCiOSkl1hU6KQYznW0w.png" /><figcaption>Bootstrapping the <strong>Kong Gateway Data Plane</strong> node with <strong>automated startup</strong> and <strong>successful connection</strong> to the <strong>Konnect Control Plane</strong></figcaption></figure><p>Once the Kong Gateway Data Plane node is successfully deployed and connected, it establishes a secure connection with the Kong Konnect Control Plane hosted in the <strong>AWS cloud India region</strong>.</p><p><strong>Upon successful synchronization:</strong></p><p>· The Data Plane node registers with the Control Plane</p><p>· Configuration state is synced automatically</p><p>· The connection status becomes visible in the Konnect UI</p><p>As part of the setup flow, a <strong>“View your data plane node”</strong> button becomes available within the <strong>Create a data plane node modal dialog</strong>. This indicates that the Data Plane has been successfully connected and is ready to handle traffic.</p><figure><img alt="View your data plane node in Kong Konnect UI." src="https://cdn-images-1.medium.com/max/1024/1*4QeYLt0754fLS1D4g6jsCw.png" /><figcaption>View Kong Gateway Data Plane Node</figcaption></figure><p>Clicking the <strong>“View your data plane node”</strong> button navigates to the <strong>Data plane nodes</strong> page under the <strong>API Gateway</strong>section in the left navigation pane of Kong Konnect. In <strong>Data plane nodes</strong> page Kong Gateway running instance can be monitored and managed from the <strong>Information</strong> and <strong>Analytics</strong> tab.</p><figure><img alt="View Data Plane Nodes in Gateway Manager." src="https://cdn-images-1.medium.com/max/1024/1*fQlM42RcfEPMLJrxhO5o9A.png" /><figcaption>Data Plane Nodes in Gateway Manager</figcaption></figure><p>As observed on the <strong>Data plane nodes</strong> page in the Gateway Manager section of Kong Konnect, the <strong>Host</strong> and <strong>Version</strong>fields are displayed for each registered node. The <strong>Host</strong> value corresponds to the <em>hostname</em> configured for the container in the Docker Compose service definition, while <strong>Version</strong> reflects Kong Gateway <em>image</em> version specified using <em>KONG_VERSION</em> parameter as defined in the <em>.env</em> environment file.</p><p>These values provide quick visibility into the runtime identity and software version of the connected Data Plane node, helping verify that the correct configuration has been applied during deployment. Kong Data Plane node is successfully installed and connected, also as seen, it is in sync with the Konnect Control Plane hosted in <strong>AWS cloud India region</strong>.</p><h3>Generating Self-Signed Certificate</h3><p>By default, Kong Gateway can process <strong>HTTP (unencrypted)</strong> traffic without requiring certificates. However, enabling <strong>HTTPS endpoints</strong> requires explicit configuration of <strong>SSL/TLS</strong> certificates. While the In Sync status confirms that the Data Plane and Konnect Control Plane are properly connected, it does not automatically provision certificates for secure client communication.</p><h4>Why Certificates Are Required</h4><p>Without configuring certificates in Konnect:</p><p>· API endpoints are exposed only over <strong>HTTP</strong>, leaving traffic unencrypted</p><p>· HTTPS requests to the gateway will fail due to <strong>TLS handshake errors</strong></p><p>· Browsers and clients will reject secure connections</p><p>· Security and compliance requirements for production environments cannot be satisfied</p><h4>Creating Self-Signed localhost Certificate</h4><p>For development, testing, or internal environments, <strong>self-signed certificates</strong> provide a practical and efficient solution. They provide the following advantages:</p><p>· Enable <strong>HTTPS</strong> endpoints on the Kong Gateway</p><p>· Test <strong>SSL/TLS</strong> behavior without relying on external Certificate Authorities</p><p>· Secure local or non-production environments</p><p>· Validate certificate configuration and gateway behavior before moving to production-grade certificates</p><p>In the following steps, a self-signed certificate for <em>localhost</em> will be generated and configured within the <strong>Certificates </strong>navigation item from the left navigation pane of Kong Konnect. This will enable Kong gateway to accept and process <strong>HTTPS-based API requests</strong>, allowing one to fully test secure routing scenarios, including port-based filtering using the Expressions router.</p><p>The certificate generation script bash file <em>self_signed_certificate.sh</em> is created in the <em>/shared</em> folder of the project, while the generated certificate and key are stored inside the <em>ssl</em><strong> </strong>subfolder.</p><pre>Project Working Directory after adding self_signed_certificate.sh bash file:<br>KongRouting/<br>├── .env<br>├── docker-compose.yaml<br>├── start.sh<br>└── kong/<br>    ├── scripts/<br>    │   └── sync/<br>    │       ├── config.yaml<br>    │       ├── kong_connect.sh<br>    │       └── routing.deck.yaml<br>    └── shared/<br>        ├── self_signed_certificate.sh<br>        ├── logs/<br>        │   ├── proxy_access.log<br>        │   ├── proxy_error.log<br>        │   ├── status_access.log<br>        │   └── status_error.log<br>        └── ssl/<br>            ├── server.crt<br>            ├── server.key<br>            ├── cluster.crt<br>            └── cluster.key</pre><p><strong>File</strong> self_signed_certificate.sh:</p><pre>#! /usr/bin/env bash<br><br>#cd kong/shared/ssl - For Windows<br>cd ssl # For unix system<br><br>openssl req -x509 -days 365 \<br>  -out server.crt -keyout server.key \<br>  -newkey rsa:2048 -nodes -sha256 \<br>  -subj &#39;/CN=localhost&#39; -extensions EXT -config &lt;( \<br>   printf &quot;[dn]\nCN=localhost\n[req]\ndistinguished_name= dn\n[EXT]\nsubjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth&quot;)</pre><p>The script navigates to the <em>ssl</em> directory and generates a self-signed certificate using OpenSSL. The script is executed by running the <em>source</em> <em>self_signed_certificate.s</em>h command in the terminal from the <em>/shared</em> directory but explicitly switches to the <em>ssl</em> folder using <em>cd</em> <em>ssl </em>command. It generates the following files:</p><p>· The <em>server.crt</em> (certificate)</p><p>· The <em>server.key</em> (private key)</p><p>These files are stored in the directory path <em>kong/shared/ssl/</em> inside the <em>ssl</em> folder of root project directory <em>KongRouting</em>. This directory path <em>kong/shared/ssl/</em> is already mounted into the container <em>(</em><em>/srv/shared/ssl</em>) via Docker volumes.</p><p>As a result, the Kong Gateway runtime can directly access these certificates for:</p><p>· HTTPS proxy endpoints (ports 443 and 8443)</p><p>· Status API TLS endpoint</p><p>This ensures that once the script is executed, the gateway is immediately capable of serving secure HTTPS traffic using the generated self-signed certificate. Add the self-signed certificate <em>server.crt</em> file in the <em>kong/shared/ssl/</em> directory as a trusted certificate in the system trust store of the Operating System and marked as trusted for all users. The browser should be able to verify the self-signed <em>localhost</em> certificate, so that the API request <a href="https://localhost:8443/">https://localhost:8443/</a> to the default HTTPS proxy port 8443 of Kong Gateway will be considered as secured by the browser. Enable this in security settings of the browser, for instance in Google Chrome by allowing imported local certificates from Operating System to be used as a trusted certificate.</p><figure><img alt="Adding self-signed localhost certificate as a trusted certificate in the browser security settings by importing local certificates from the Operating System." src="https://cdn-images-1.medium.com/max/1024/1*s70eV3TsGgPgjoUixTOtMA.png" /><figcaption><em>Importing local certificate from the Operating System as Trusted Certificate</em></figcaption></figure><h4>Uploading Certificate in Kong Konnect and Configuring SNI</h4><p>Navigate to Certificates page in Kong Konnect UI from the API Gateway section under Certificates navigation menu item in left navigation pane.</p><figure><img alt="Kong Konnect Certificates Page to Manage SSL/TLS Certificates with Kong Konnect Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*ffzcexJbI1aGwyJ--lR_1Q.png" /><figcaption>Kong Konnect Certificates Page</figcaption></figure><p>The <strong>Certificates page</strong> is where one manages SSL/TLS certificates associated with Kong Konnect Control Plane.</p><p>1. Click <strong>“New certificate” </strong>button</p><p>2. Provide the following details:</p><p>▪ <strong>Certificate</strong> → Paste the contents of <em>server.crt</em> under <strong>Cer</strong>t input field</p><p>▪ <strong>Private Key</strong> → Paste the contents of <em>server.key</em> under <strong>Key</strong> input field</p><p>▪ <strong>SNIs </strong>→ Add <em>localhost</em> to match the Common Name value in self-signed certificate issued from Client Browser</p><p>3. Click <strong>Save</strong></p><p>This registers the certificate with the Kong Konnect Control Plane.</p><figure><img alt="Configuring the Certificate and Private Key for Kong Konnect Control Plane to Add new Certificate and Adding the SNI for Konnect Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*I8lbLMJyaDc8ZNBoJUcAjg.png" /><figcaption>Adding New Self-Signed Certificate and Private Key with SNIs</figcaption></figure><figure><img alt="Saving the new self-signed Certificate for Kong Konnect Routing Control Plane in New Certificates Page." src="https://cdn-images-1.medium.com/max/1024/1*R0kFwdjcW1e2Ie7-_pf9ug.png" /><figcaption>Saving The Self-Signed Certificate for Kong Konnect Routing Control Plane in New Certificates Page</figcaption></figure><p>Click the “<strong>Save</strong>” button to add the new certificate with the configured certificate, private key and SNIs into Konnect Control Plane. The user then navigates to the Certificate Detail page in Kong Konnect displaying the configuration details of the new Certificate that has been registered with the Kong Konnect Control Plane.</p><figure><img alt="Certificate Detail Page displaying the configuration details of the newly added Certificate along with its ID created by Kong Konnect Platform." src="https://cdn-images-1.medium.com/max/1024/1*oWdgU6uahvWmFxhmURV3xw.png" /><figcaption>Certificate Detail Page</figcaption></figure><p>A message <em>Successfully created certificate</em> pops up in Konnect UI from the bottom once the new certificate has been saved and registered with the Konnect Control Plane which is Routing in our case. An ID for the Certificate is also created by Kong Konnect Platform. This ID will be later used to map the certificate with SNI added into Kong Konnect.</p><p>After uploading the certificate, configure the <strong>SNI</strong> to ensure that incoming HTTPS requests are correctly matched to the certificate. Select the Certificates navigation item again from left navigation pane in Kong Konnect UI. Navigate back to the Certificates page in Kong Konnect UI which shows the <em>self-signed-local</em> certificate under Certificates tab.</p><h4>Configuring SNI</h4><p>Select the <strong>SNIs tab</strong> in the Certificates page. Notice that the SNI added while creating the new certificate is never added to the SNIs section of the Certificates page in Kong Konnect UI. Click on New SNI button to navigate to the New SNI page in Kong Konnect UI.</p><figure><img alt="Configuring a new SNI mapping from Kong Konnect UI." src="https://cdn-images-1.medium.com/max/1024/1*tufTAlbdK_MNMwr2UmVkaw.png" /><figcaption>Configuring a New SNI from Kong Konnect UI</figcaption></figure><p>Provide the following details for the fields in New SNI page:</p><p>1. Name → Add <em>localhost</em>, the Common Name of Self-Signed Certificate added into the Certificates page</p><p>2. Tags → Add self-signed-local text for this field.</p><p>3. SSL Certificate ID → Select the ID of the newly added certificate from the dropdown option</p><p>4. Click <strong>Save</strong></p><figure><img alt="Adding a new SNI Mapping localhost to the self-signed localhost certificate created in Kong Konnect Routing Control Plane." src="https://cdn-images-1.medium.com/max/1024/1*DePJSJQu6Rd-5BMK0CZc0w.png" /><figcaption>Add new SNI mapping to a Certificate added into Kong Konnect Control Plane</figcaption></figure><p>SNIs (Server Name Indications) allow the Kong Gateway to determine which SSL/TLS <strong>certificate</strong> to use based on the <strong>hostname</strong> in the client request. Here, the client is the Browser that sends GET API request via Kong Gateway. It allows to use multiple domain names to securely serve requests through the same Kong Gateway. Saving this SNI maps the <em>localhost</em> domain in Client’s request to the newly added self-signed certificate in the Kong Konnect Certificates page.</p><figure><img alt="SNI added successfully in the Kong Konnect Certificates Page mapping the self-signed certificate to request with localhost domain." src="https://cdn-images-1.medium.com/max/1024/1*IGQmeXkgUhwOuD1gxqISAA.png" /><figcaption>SNI Added to the SNIs tab in Certificates Page</figcaption></figure><p>A message <em>Successfully created SNI</em> pops up in Konnect UI from the bottom once a new SNI has been created and added to the Kong Konnect Control Plane, mapping the self-signed certificate to a hostname provide in the <strong>Name</strong> field.</p><h4>Validating Kong Gateway Proxy &amp; Status API</h4><p>Now, one can make a request <a href="https://localhost:8443/">https://localhost:8443</a> from the browser to the Kong Gateway on HTTPS enabled secured default port 8443.</p><figure><img alt="Secured API request to Kong Gateway Proxy URL on default TLS enabled Port 8443. The API request on localhost is verified as secure by the Browser." src="https://cdn-images-1.medium.com/max/1024/1*ehPsDKPAv9LYynNvABCjJw.png" /><figcaption>Browser Request to Kong Gateway Proxy URL on secured default port 8443</figcaption></figure><p><strong>Browser initiates HTTPS </strong>connection to localhost:8443 the default HTTPS port of Kong Gateway:</p><p>· Kong presents the newly added self-signed certificate during TLS handshake with the client browser</p><p>· Browser encrypts the connection using the certificate sent by Kong Gateway</p><p>· Kong decrypts during TLS termination and doesn’t find any matching routes</p><p>· Response is encrypted back to the browser with 404 response status stating <em>no Route matched with those values</em></p><p>The Browser considers the HTTPS connection to <em>localhost:8443</em> secure and verified by localhost.</p><p>To check the health of Kong Gateway and verify if API requests can be served via the Kong Gateway send a request to the Kong Status API endpoint <a href="https://localhost:8101/status/ready">https://localhost:8101/status/ready</a> from the Browser.</p><p>In Kong Docker Compose setup, the Status API listener is configured through the container <em>environment</em> section using KONG_STATUS_LISTEN=0.0.0.0:8101 http2 ssl. The ssl flag instructs Kong to enable TLS on the Status API port <em>8101</em>, so the gateway <strong>expects a TLS handshake</strong> when a client connects to <em>8101</em>. Therefore, health checks must be sent as <strong>HTTPS</strong>requests (for example, <a href="https://localhost:8101/status/ready);"><em>https://localhost:8101/status/ready</em>);</a> a plain HTTP call to <a href="http://localhost:8101"><em>http://localhost:8101</em></a> would fail because the connection is not negotiated over TLS.</p><figure><img alt="An HTTP call to http://localhost:8101 would fail because the connection is not negotiated over TLS on port 8101. Kong Gateway is configured to accept TLS handshakes only for secured communication on the Status listener port 8101." src="https://cdn-images-1.medium.com/max/1024/1*D11uydYT8m3a48_INIVprA.png" /><figcaption>HTTP call to Kong Status API</figcaption></figure><p>Since the Status API listener is TLS-enabled, an HTTP request to port 8101 fails because Kong expects an HTTPS (TLS handshake) connection.</p><figure><img alt="The health of Kong Gateway is Verified by sending a secure HTTPS request to Status API endpoint of Kong Gateway on Port 8101 which is enabled to receive TLS connection requests." src="https://cdn-images-1.medium.com/max/1024/1*Dx3gNhFxVkY1woAaZ3Eubg.png" /><figcaption>Kong Status API endpoint connection is Secure and Verified by Kong Gateway</figcaption></figure><figure><img alt="A 200 Ok response status code is received from Status API with message as “ready” indicating that Kong Gateway is connected with Kong Konnect Routing Control Plane and ready to accept inbound API requests." src="https://cdn-images-1.medium.com/max/1024/1*HAlPqtes6yZgjkdxIBne7g.png" /><figcaption>Kong Gateway Health Check via TLS based request to Status API</figcaption></figure><p>When clients make HTTPS requests via Kong Gateway with the hostname <em>localhost</em> (or when the <strong>TLS</strong> handshake includes <em>localhost</em> as the Server Name Indication), Kong Gateway will:</p><p>1. Select the <strong>self-signed certificate</strong> during the TLS handshake based on the SNI matching</p><p>2. Kong Gateway will<strong> Present that self-signed certificate</strong> to the Client</p><p>3. <strong>Terminate SSL/TLS</strong> using the private key associated with the <strong>certificate</strong></p><p>4. <strong>Decrypt the request</strong> and forward it to upstream services</p><p>5. <strong>Response is encrypted</strong> back to the Client</p><p>A <strong>200 Ok</strong> response status code from Status API with message as “<strong>ready</strong>” indicates that Kong Gateway is setup properly to serve requests from Clients by forwarding them to upstream services receiving response and sending it back to those Clients that issued these requests, in a seamless manner.</p><p>This completes the certificate setup required to securely expose APIs over HTTPS and enables further testing of <strong>port-based Expressions routing</strong> on the Kong Gateway.</p><p>Next, in <a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-611822f26fc2"><strong>Part-3</strong></a> of this blog series, the Kong <em>echo API and HTTPBin</em> API backend services will be onboarded into the Kong Konnect Control Plane using <strong>automated Bash scripts</strong> with multiple <em>decK </em>operations. We will also take a <strong>backup</strong> of the Kong Konnect Control Plane configuration state as the single source of truth, and <strong>patch</strong> the Kong declarative configuration file to <strong>automatically transform</strong> traditional route paths into <strong>Expressions Routes</strong> while<strong> injecting</strong> the <strong>Request-Termination</strong> plugin to handle unnecessary browser /favicon.ico requests.</p><h4>Blog Series — <a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-611822f26fc2">Part-3</a></h4><p><em>Automated Onboarding of Backend API Services into Kong Konnect Using decK and Declarative Configuration with Backup Synchronization</em></p><p><a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-611822f26fc2">Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port…</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dde0a6af8c13" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Use of Expressions Routing in Kong Gateway to Filter Inbound API Requests by Destination Port…]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-number-9c23e4908c26?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/9c23e4908c26</guid>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[docker-docker-compose]]></category>
            <category><![CDATA[kong-konnect-api-platform]]></category>
            <category><![CDATA[apiops]]></category>
            <category><![CDATA[kong-plugin]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Sun, 10 May 2026 06:00:13 GMT</pubDate>
            <atom:updated>2026-05-10T12:11:55.268Z</atom:updated>
            <cc:license>https://creativecommons.org/licenses/by-nc-nd/4.0/</cc:license>
            <content:encoded><![CDATA[<h3><strong>Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port Number — Part-1</strong></h3><figure><img alt="Technical banner illustration showing Kong Gateway Expressions Routing for filtering inbound API requests by destination port number. The diagram depicts API clients sending traffic to a self-managed Kong Gateway Data Plane managed by a Kong Konnect Control Plane in the India Region." src="https://cdn-images-1.medium.com/max/1024/1*f4IAE4OPC47sP_dPpKUsFA.png" /><figcaption>Kong Gateway Enterprise filtering inbound API requests by Destination Port Number</figcaption></figure><p>Shubhojit Dasgupta — Independent API Architect</p><p>This blog series on Kong Gateway Expressions Router flows across <strong>four connected parts</strong>, with each part building progressively on the previous one to provide a complete understanding of expressions-based API traffic routing in Kong Gateway.</p><p>In this part of the blog series, we begin by exploring the API traffic flow architecture, gaining a brief understanding of Kong Expressions syntax, its advantages, and reviewing the overall solution overview of the routing implementation covered throughout the series. This part also walks through setting up the Kong Konnect API Platform and generating the Kong Konnect Personal Access Token required for securely managing the Kong Gateway Data Plane from the Konnect Control Plane.</p><h3>Default Gateway Listening Ports</h3><p><strong>·</strong> <strong>8000</strong>: HTTP (unencrypted) proxy port for inbound API requests</p><p><strong>·</strong> <strong>8443</strong>: HTTPS (TLS-encrypted) proxy port for inbound API requests</p><p>Kong Gateway sits in front of the upstream service. Client applications send requests to Kong, and Kong forwards matching requests to the appropriate upstream API (for example, a “get customer details” capability).</p><h3>How an Upstream API Is Onboarded</h3><p>The upstream provider’s API is onboarded into Kong through the <strong>Kong Konnect Control Plane</strong>. Configuration — such as the API definition, routes, and policies — is synced from <strong>Konnect</strong> to a <strong>self-managed Kong Data Plane</strong> (runtime gateway).</p><p>The client application uses the <strong>Kong Gateway proxy URL</strong> as the API’s server URL and sends requests to the route path configured in Kong.</p><h4>Request/Response Flow and Traffic Visibility</h4><p>1. The client sends a request to Kong (HTTP on 8000 or HTTPS on 8443).</p><p>2. Kong matches the request to a route and selects the associated service.</p><p>3. Kong forwards the request to the configured upstream backend service.</p><p>4. The upstream returns a response, which Kong relays back to the client.</p><figure><img alt="Kong Konnect API Traffic Flow." src="https://cdn-images-1.medium.com/max/1024/1*DRsggH-SdWwzdpzEfNcIVw.png" /><figcaption>Kong Konnect API Traffic Flow</figcaption></figure><p>API traffic (request/response payloads and runtime details) remains within the self-managed data plane environment; it is <strong>not exposed</strong> to the Konnect Control Plane.</p><p>In a traditional Kong Gateway configuration, route selection is typically based on request attributes such as the URL path, host, method, and headers. In that model as seen above the Kong Gateway runtime selects the Route whose configured path matches the incoming request. However, Kong Gateway can listen on multiple HTTPS ports exposed by the runtime for secure client communication, and in some use cases, the destination port is just as important as the request path. If one wants to allow a client application to access an API only when it sends the request to a specific HTTPS port exposed by Kong Gateway, path-based routing alone is not sufficient. In such cases, Kong must be configured to use the Expressions Router, which enables route matching based on both the request path and the destination port, allowing more precise control over how client requests are filtered and routed.</p><h3>Takeaway Skills</h3><p>This blog will help to understand and implement in an hands-on manner installing &amp; configuring a self-managed Kong Gateway Data Plane running in your computer, synced with the Kong Konnect Control Plane, and ready for Expression routing. The blog covers the following with complete code, implementation and simplifications so that one can try out a successful implementation of the solution discussed in this blog for a specific use case in their computer. Kong Konnect free subscription for <strong>30 days</strong> can also be used to implement the solution in this blog.</p><p>1. Kong Gateway Expressions Router, its use case and its advantages, and Solution overview.</p><p>2. Login to Kong Konnect Plus Account and setup Personal Access Token. This token shall be stored in a special file to be used with decK for securely and declaratively onboarding APIs, plugins and configurations into Kong Konnect API platform.</p><p>3. Provisioning Kong Konnect Control Plane and a Self-Managed Kong Gateway Data Plane.</p><p>4. Generating <strong>self-signed localhost certificate</strong> and <strong>key</strong>. This will be used to allow secure <strong>HTTP/2 </strong>connections to Kong’s proxy and health status endpoints. So a request <a href="https://localhost:8101/status/ready">https://localhost:8101/status/ready</a> will be considered secured by your browser locally with Kong Gateway responding with health check status.</p><p>5. Installation of Kong Gateway version <strong>3.14.0.1</strong> with <strong>Expressions</strong> <strong>router</strong> enabled.</p><p>6. Configuring <strong>self-signed localhost certificate </strong>&amp; <strong>key</strong> enabling <strong>TLS</strong> on Kong Gateway proxy and status ports with two secured ports listening for incoming API requests. This allows client Apps to make Https based API request to Upstream backend service using localhost via the Kong Gateway.</p><p>7. Onboarding APIs and plugins declaratively using deck into Kong Konnect Control Plane.</p><p>8. Adding Kong <strong><em>request-termination</em></strong> <strong>plugin</strong> to prevent unnecessary requests to <em>/favicon.ico</em> path by browsers.</p><p>9. Bash <em>.sh</em> script file to <strong>automate</strong> the execution of multiple <strong>decK </strong>commands and installation of Kong Gateway.</p><p>10. Testing and <strong>Validating</strong> if API requests are getting filtered by destination port numbers in Kong Gateway.</p><p>11. Automated <strong>Backup</strong> and <strong>Reconciliation</strong> of the Kong Konnect Control Plane Configuration <strong>State</strong>.</p><h3>Pre-requisites</h3><p>1. Good laptop, internet connection and Kong Konnect SaaS API platform account.</p><p>2. Docker desktop and Docker compose installed.</p><p>3. CLI decK version 1.59.x to declaratively configure Kong Konnect Platform.</p><p>4. OpenSSL version 3.6.x.x to generate self-signed certificate and key for the Kong Gateway.</p><p>To learn how to install decK visit <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-6-d61463dd3711">dynamic-routing-part-6</a> blog and refer <a href="https://fixmycert.com/guides/openssl-installation">site</a> to install OpenSSL. Installation of decK and OpenSSL will not be covered in this blog. The decK commands used, shall be explained with full code description.</p><h3>Kong Gateway Expressions Router</h3><p>The routing engine in Kong Gateway (available from version 3.0+) for both traditional and expressions router is ATC (Abstract tree classifier) built using Rust language for high security with performance. Expressions router provides a Domain Specific Language (DSL) for defining complex routing rules. Instead of configuring routes with JSON criteria, that one does using the traditional route mode, one can write logical <strong>predicates </strong>and<strong> expressions</strong> that evaluate inbound API requests. Expressions router ensures good runtime matching performance in the gateway by providing expression like syntax to match specific route comparisons using predicates containing non-regex equality checks that are not available in traditional router.</p><p>A predicate has three parts:</p><pre>http.path ^= &quot;/echo&quot;</pre><p>· <strong>Field</strong> (http.path): Value extracted from the incoming API request issued by the Client Application</p><p>· <strong>Operator</strong> (^=): The comparison to perform. It checks if the given request path starts with specified value</p><p>· <strong>Constant</strong> value (“<em>/echo</em>”): What the field is compared against</p><p>Predicates can be combined using <strong>logical operators</strong> (&amp;&amp;, ||, !) to form complex expressions.</p><h4>Expressions Router Performance Benchmark</h4><p>The <strong>Expressions router in Kong Gateway is generally preferred</strong> because it provides a more efficient and flexible routing model: it uses a DSL-based approach that enables optimized comparisons (e.g., non-regex equality checks), short-circuit evaluation, and better handling of complex routing logic, which translates to improved runtime matching performance and scalability — especially when dealing with large numbers of routes or regex-heavy configurations. Kong itself recommends using the expressions router for new deployments because it is more powerful and expressive than the legacy JSON-based routing model.</p><figure><img alt="Kong Expressions Routing vs Traditional JSON-based Routing Performance Benchmark." src="https://cdn-images-1.medium.com/max/1024/1*eftLfqnr39wF0oVoB1_VTQ.png" /><figcaption>Kong Expressions Routing vs Traditional JSON-based Routing</figcaption></figure><p><strong>Delay using Expressions routing</strong> in scenarios where backward compatibility or simplicity is critical. The traditional JSON router is still relevant when migrating legacy configurations, when teams prefer a simpler declarative structure without introducing a DSL, or when existing tooling depends on the older routing format. Kong recommends using JSON format traditional router when manipulating routes in APIOps pipeline via <em>decK file patch</em> commands. However, in the blog it will be shown how <em>deck file patch</em> commands in bash script elegantly convert existing traditional routes automatically by replacing <em>paths: [“</em><em>/api/v1”]</em> with <em>expression:</em>http.path == “/api/v1” &amp;&amp; http.method == “GET”<em> </em>without downtime or full config rewrites.</p><h4>Advantages</h4><p>1. Expressions Router is designed for better runtime matching performance by supporting efficient comparisons such as exact and prefix-based matching, instead of relying heavily on regex. This helps reduce routing overhead and improves request processing speed, especially in high-traffic API environments.</p><p>2. With its domain-specific language (DSL), the Expressions Router allows to define more advanced routing logic than traditional routing. One can match requests based on paths, headers, query parameters, source IPs, destination ports, and SNI, making it easier to implement precise and sophisticated traffic control.</p><p>3. In Konnect environments with many services and routes, the Expressions Router helps improve scalability by allowing teams to combine multiple routing rules into a single expression. Fewer route objects mean cleaner configuration, simpler management, and more efficient route evaluation as deployments grow.</p><p>4. The Expressions Router gives developers more control over how routes are evaluated through route priorities and logical operators such as <strong>&amp;&amp;</strong> and <strong>||</strong>. This optimises routing behavior by placing more likely matched routes before (as in, <strong>higher priority</strong>) less frequently matched routes., reduce unnecessary regex usage, and maintain cleaner, more readable configurations over time.</p><h3>API Traffic Filtering Use Case</h3><p>Consider a Kong Gateway deployment that exposes multiple upstream services through <strong>different gateway listener ports</strong>, while still sharing a single logical hostname. This pattern is common in platform engineering when isolating traffic flows without introducing additional domains or complex routing layers.</p><p>In this scenario, Kong is configured with two HTTPS listener ports:</p><ul><li><strong>Port 443</strong> → serves a local <strong>echo service</strong></li><li><strong>Port 8443</strong> → serves the public <strong>HttpBin service</strong> over the internet</li></ul><p>The key requirement is strict traffic segregation: a request should only match a route if <strong>both the HTTP attributes (path/method)</strong> and the <strong>destination port</strong> are correct.</p><h4>Routes and Expressions</h4><p>Two routes are defined, each tightly scoped using expressions:</p><p><strong>Echo service (port 443)</strong></p><ul><li>Path: <em>/echo</em></li><li>Method: GET</li><li>Expression: http.method == &quot;GET&quot; &amp;&amp; http.path ^= &quot;/echo&quot; &amp;&amp; net.dst.port == 443</li></ul><p>This ensures the route only matches:</p><ul><li>HTTP GET requests</li><li>Paths starting with <em>/echo</em></li><li>Requests arriving specifically on port 443</li></ul><p><strong>HttpBin service (port 8443)</strong></p><ul><li>Paths: <em>/anything</em> and <em>/status/&lt;code&gt;</em></li><li>Combined using logical OR (||) operator</li><li>Expression: (http.path ~ r#&quot;^/status/(?P&lt;status_code&gt;[1-5]\d{2})$&quot;# || http.path ^= &quot;/anything&quot;) &amp;&amp; net.dst.port== 8443</li></ul><p>This route matches:</p><ul><li><em>/status/&lt;code&gt;</em> where <em>&lt;code&gt;</em> is a valid HTTP status (100–599)</li><li>Any path starting with <em>/anything</em></li><li><strong>Only</strong> when the request arrives on port 8443</li></ul><p>The critical detail here is that <strong>port matching is part of the routing condition</strong>, not an external configuration. This gives deterministic control over how traffic is segmented at the gateway level.</p><h4>Expected request/response behavior (Success vs 404 cases)</h4><p>With port-aware expressions in place, routing becomes unambiguous and predictable.</p><p><strong>Successful requests</strong></p><ul><li>GET <em>https://&lt;gateway-host&gt;:443/echo</em></li><li>Matches echo route</li><li>Proxied to echo upstream</li><li>Response returned via Kong</li><li>GET <em>https://&lt;gateway-host&gt;:8443/status/200</em></li><li>Matches HttpBin <em>/status/&lt;status-code&gt;</em> route path</li><li>Proxied to HttpBin</li><li>Returns HTTP 200 response</li><li>GET <em>https://&lt;gateway-host&gt;:8443/anything</em></li><li>Matches HttpBin <em>/anything</em> route path</li><li>Proxied successfully to the <em>/anything</em> endpoint of HttpBin upstream service</li><li>HttpBin service returns the request headers as response with HTTP 200 Ok response status back to client via Kong Gateway</li></ul><p><strong>Rejected requests (port mismatch → 404)</strong></p><ul><li>GET <em>https://&lt;gateway-host&gt;:8443/echo</em></li><li>Path matches <em>/echo</em>, but port is incorrect</li><li><strong>No route match</strong></li><li>Kong returns: <strong>404</strong> No matching routes found</li><li>GET <em>https://&lt;gateway-host&gt;:443/status/200</em></li><li>Path matches HttpBin pattern, but port is incorrect</li><li><strong>No route match</strong></li><li>Kong returns: <strong>404</strong> No matching routes found</li><li>GET <em>https://&lt;gateway-host&gt;:443/anything</em></li><li>Same outcome: <strong>404 due to port mismatch</strong></li></ul><p>API request <strong>Filtering is performed on the gateway’s destination port (</strong>net.dst.port<strong>), not based on upstream service configuration.</strong> The upstream is never reached unless the full expression evaluates to true. The “<em>gateway-host</em>” is the Kong Gateway proxy URL which is <em>localhost</em> for this blog secured by a self-signed certificate. Self-signed certificate and key are stored in separate files with absolute path of those files added to environment properties in Kong Gateway. Load the self‑signed cert/key into Kong so it can present <em>localhost</em> over HTTPS and decrypt incoming traffic before routing upstream.</p><h4>Handling /favicon.ico with request termination</h4><p>Browsers automatically issue background requests to <em>/favicon.ico</em>, which can introduce unnecessary noise and unintended upstream calls.</p><p>To prevent this, a <strong>request-termination plugin</strong> is configured to intercept <em>/favicon.ico</em> requests on both ports (<strong>443 and 8443</strong>) and return an immediate response. This ensures such requests are handled at the Kong gateway layer and never forwarded to either the <em>echo</em> or <em>HttpBin</em> upstreams. Throughout this blog series, we will verify the <strong>operational</strong> behavior of the <strong>request-termination plugin</strong> within Kong Gateway.</p><h3>Solution Overview</h3><p>Kong Gateway enables expressions routing by setting property `<em>KONG_ROUTER_FLAVOR</em>` to `<em>expressions</em>` in the environment configuration section of Kong Gateway installation in its docker compose service container. By setting KONG_ROUTER_FLAVOR=expressions in Kong container’s environment (Docker Compose), Kong allows routes to be defined using expression like syntax using fields such as net.dst.port, http.path, and http.method. This solution uses Kong Gateway with expressions router to enforce port-based API traffic isolation and handle unnecessary <em>/favicon.ico</em> browser requests efficiently. Kong Gateway listens on two secured ports that is tls enable for receiving HTTPS based requests one on port 443 for the Echo service and other on port 8443 for the httpbin service and evaluates incoming requests against route expressions that include equality checks on net.dst.port field.</p><figure><img alt="API Traffic Segregation with Expressions based Routing Solution Architecture." src="https://cdn-images-1.medium.com/max/1024/1*87AMCYTTBXRbMdoy8rPwaw.png" /><figcaption>Solution Architecture</figcaption></figure><p>Requests matching expression and port are forwarded to the appropriate upstream, service (green arrow), and responses return to the client (blue dashed arrow). Browsers sending requests for <em>/favicon.ico</em> on either port are intercepted by <strong>request-termination plugin</strong>, which returns a response directly from Kong Gateway without calling any upstream (orange arrow). If a request arrives on the wrong port but the path matches for the intended route (e.g., <em>/echo</em> on port 8443 or <em>/anything</em> on port 443), Kong returns <em>404 No matching route found</em> response immediately (red dashed arrow from right to left), and the request is not forwarded to upstream. This ensures strict port-based routing, clean separation of API traffic and reduced noise from unnecessary browser requests (<em>/favicon.ico</em>).</p><h3>Kong Konnect Login</h3><p>Login to Kong Konnect using the link <a href="https://cloud.konghq.com/login">https://cloud.konghq.com/login</a> and Sign In with your email and credentials.</p><figure><img alt="Sign In into Kong Konnect API Platform." src="https://cdn-images-1.medium.com/max/1024/1*dz3SfKOcKv2EGLcyhe7srg.png" /><figcaption><em>Kong Konnect Sign In Page</em></figcaption></figure><h3>Setting Up Kong Konnect Platform</h3><p>Create an Organization and give it a proper name. Enable MFA enrolment as it is strongly recommended by checking the box. When enabled, users who sign in with a username and password must use multi-factor authentication (MFA).</p><figure><img alt="Create an Organization for your Kong Konnect Platform." src="https://cdn-images-1.medium.com/max/1024/1*fk0f3ZijHBAdUwqvg0RLWg.png" /><figcaption>Create an Organization</figcaption></figure><p>This can be updated in security settings under Organization section of left-navigation pane in Kong Konnect Platform.</p><figure><img alt="Kong Konnect Organization Security Settings Page." src="https://cdn-images-1.medium.com/max/1024/1*9dRzYwjoT-bRQcPVhfxjCg.png" /><figcaption><em>Kong Konnect Organization Security Settings</em></figcaption></figure><p>Disable multi-factor authentication if required but ensure Personal access tokens is enabled as decK CLI (Command Line Interface) tool authenticates to Kong Konnect using Personal Access Token (PAT) and interacts with the Konnect Control Plane APIs to declaratively manage and sync gateway configuration. The decK CLI tool pushes configuration (services, routes, plugins, etc.) to the Kong Konnect Control Plane, which then propagates it to connected Data Planes.</p><p>After the organization name has been created, select a Konnect region to determine where the Kong Konnect Control Plane, fully-managed by Kong team in AWS cloud is hosted and operated. Choosing the appropriate geographic region is essential for meeting <strong>data residency</strong>, privacy, and <strong>regulatory compliance</strong> requirements. Regional deployment also helps keep Konnect closer to end users and supporting infrastructure, which can improve <strong>operational alignment</strong> and performance. Some resources such as Consumers &amp; Gateway Services are geo-specific and exist only within the region where they are created, while authentication, billing, and usage remain shared across Konnect regions. In this blog India is selected as the region, so the Kong Konnect Control Plane gets provisioned in AWS cloud and hosted in India, <strong>Mumbai (ap-south-1)</strong> region being fully-managed by Kong Konnect team following the best practices in <strong>AWS cloud</strong>.</p><figure><img alt="Select a region for Kong Konnect Orgnization where Control Planes will be hosted." src="https://cdn-images-1.medium.com/max/1024/1*Bt90sXlm1u6u9wtbv--fIQ.png" /><figcaption>Select a Region</figcaption></figure><p>Any available Konnect region can be selected, ideally the geographic location closest to the team &amp; core infrastructure and the port-based routing solution in this blog remains unchanged. The only adjustment is ensuring that tooling targets the region-specific Konnect Control Plane API endpoints. When using decK to synchronize configuration, the Control Plane address must point to the selected region (for example, via — konnect-addr), so all reads and writes occur against the correct regional Control Plane.</p><p>After selecting <strong>India</strong> region for Konnect organization, ensure that automation tools point to the <strong>India (Mumbai / ap-south-1)</strong> Control Plane API endpoint. For decK, this is done by setting the --konnect-addr flag to the India regional API base URL:</p><pre>deck gateway ping \<br>  --konnect-token-file ${TOKEN_FILE} \<br>  --konnect-control-plane-name ${CONTROL_PLANE} \<br>  --konnect-addr ${CONTROL_PLANE_ADDR}</pre><p>The value for --konnect-addr flag is provided through a placeholder that is populated from the CONTROL_PLANE_ADDR environment variable. This keeps the command portable across Konnect regions by changing only the environment variable value.</p><p>In this blog, <strong>India</strong> region is used, so <a href="https://in.api.konghq.com"><em>https://in.api.konghq.com</em></a> is configured as the value for --konnect-addr flag to allow <em>decK</em> to connect &amp; synchronize configuration with Kong Konnect Control Planes hosted in <strong>India, Mumbai (ap-south-1)</strong>. These Geo specific Kong Konnect Control Plane APIs are documented in <a href="https://developer.konghq.com/deck/gateway/konnect-configuration/">decK Konnect configuration</a> guide.</p><p>The default API decK uses is <a href="https://us.api.konghq.com/">https://us.api.konghq.com</a>. The default region selected, if not specified, is the US region.</p><p>After creating the Kong Konnect Organization, assigning an appropriate name, and selecting the region, the next step is to generate a <strong>Kong Konnect Personal Access Token (PAT)</strong>. This token is used to authenticate API calls and allows tools such as <strong>decK</strong> to connect to Konnect and manage configuration in the selected Control Plane.</p><p>Before generating the Kong Konnect Personal Access Token, create the local project structure used to store scripts and decK configuration. Create a project root folder named <em>KongRouting</em>, then create a <em>kong</em> folder inside it. Under kong, create <em>scripts/sync </em>folder, and add a decK state file named <em>routing.deck.yaml</em> in the <em>sync</em> folder. The file name can be anything. A recommended naming convention is <em>&lt;Control-Plane-Name&gt;.deck.yaml</em>.</p><pre>Project Folder Structure:<br>KongRouting/<br>└── kong/<br>    └── scripts/<br>        └── sync/<br>            └── routing.deck.yaml</pre><h3>Generate Kong Konnect Personal Access Token</h3><p>Kong Personal Access Tokens (PATs) are essential for authenticating with Kong Konnect APIs and CLI tools. They provide secure, programmatic access to your Konnect resources and are required for automation, CI/CD pipelines, and various Kong tools. A Personal Access Token is a secure credential that grants API access to Kong Konnect with the same permissions as your user account. PATs are used by:</p><ul><li><strong>Kong CLI tools</strong> (kongctl, decK)</li><li><strong>CI/CD pipelines</strong> for automated deployments</li><li><strong>Custom applications</strong> integrating with Konnect APIs</li><li><strong>Infrastructure as Code</strong> tools like Terraform</li></ul><p>To generate a Personal Access Token in Kong Konnect, navigate to your user profile by clicking the profile icon in the top-right corner of the Konnect UI. From the dropdown menu, select <strong>“Personal Access Tokens”</strong> to access the Kong Konnect Personal Access Token management page, where one can create and manage tokens for authenticating with Konnect APIs and tools such as decK.</p><figure><img alt="Navigating to Kong Konnect Personal Access Token Management Page." src="https://cdn-images-1.medium.com/max/1024/1*Nnfb1Lnef2v1gnzo9pqYFQ.png" /><figcaption><em>Navigating to Kong Konnect Personal Access Token Management Page</em></figcaption></figure><h4>Generate a New Token</h4><figure><img alt="Generate Kong Konnect Personal Access Token." src="https://cdn-images-1.medium.com/max/1024/1*pnzcxNVz22_XWjXCY2x1ag.png" /><figcaption>Generate Kong Konnect Personal Access Token</figcaption></figure><ol><li>Click the <strong>“Generate Token”</strong> button</li><li>Provide a descriptive name for token (e.g., “CI/CD Pipeline”, “Local Development”, “Terraform Automation”)</li><li>Optionally set an expiration date for enhanced security</li><li>Click <strong>“Generate”</strong></li></ol><h4>Copy and Store the Token Securely</h4><figure><img alt="Copy the Kong Konnect Personal Access Token and Store it Securely." src="https://cdn-images-1.medium.com/max/1024/1*zVJZknrB-mMbq-T01tO-Xg.png" /><figcaption>Copy and Securely Store the Kong Konnect Personal Access Token</figcaption></figure><p>The Kong Konnect Personal Access Token is displayed only once at the time of creation. Ensure to copy and securely store it in the <em>routing.deck.yaml</em> file within the <em>sync</em> directory for use with decK.</p><p>Within the root project directory <em>KongRouting</em>, create a <em>.env</em> file to centralize all environment variables required for the Kong deployment and its dependent services. Alongside this, include a <em>docker-compose.yaml</em> file to define the containerized topology and a <em>start.sh</em> script to bootstrap Kong Gateway with configurations dynamically interpolated from the <em>.env</em> file.</p><p>Additionally, create a <em>shared/</em> directory under the kong/ subdirectory in <em>KongRouting</em> to manage persistent and security-related artifacts. Inside this directory, define two subfolders:</p><p>· <em>logs/</em> — used to store proxy and status logs generated by the Kong Gateway container</p><p>· <em>ssl/</em> — used to store TLS assets, including cluster and server certificates along with their corresponding private keys</p><pre>Updated Project Working Directory:<br>KongRouting/<br>├── .env<br>├── docker-compose.yaml<br>├── start.sh<br>└── kong/<br>    ├── scripts/<br>    │   └── sync/<br>    │       └── routing.deck.yaml<br>    └── shared/<br>        ├── logs/<br>        │   ├── proxy_access.log<br>        │   ├── proxy_error.log<br>        │   ├── status_access.log<br>        │   └── status_error.log<br>        └── ssl/<br>            ├── server.crt<br>            ├── server.key<br>            ├── cluster.crt<br>            └── cluster.key</pre><p>Next, in <a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-dde0a6af8c13"><strong>Part-2</strong></a>, we will provision the Kong Konnect Control Plane with a Self-Managed Kong Gateway Data Plane, install &amp; and configure the Self-Managed Kong Gateway runtime, generate a self-signed TLS certificate, then upload it into the Kong Konnect Platform, and finally validate the operational behavior of the Kong Gateway Proxy and Status API endpoints.</p><h4><strong>Blog Series — </strong><a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-dde0a6af8c13"><strong>Part-2</strong></a><strong>:</strong></h4><p><em>Provisioning Kong Konnect Control Plane with Self-Managed Kong Gateway</em></p><p><a href="https://medium.com/@shubhojit.dasgupta/use-of-expressions-routing-in-kong-gateway-to-filter-inbound-api-requests-by-destination-port-dde0a6af8c13">Use of Expressions Routing in Kong Gateway, to Filter Inbound API Requests by Destination Port…</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9c23e4908c26" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI Driven Unified API Layer]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/ai-driven-unified-api-layer-d6d14a6da5d4?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/d6d14a6da5d4</guid>
            <category><![CDATA[kong-api-gateway]]></category>
            <category><![CDATA[wundergraph]]></category>
            <category><![CDATA[grafana-alloy]]></category>
            <category><![CDATA[dreamfactory]]></category>
            <category><![CDATA[grafana-loki]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Mon, 13 Oct 2025 14:00:25 GMT</pubDate>
            <atom:updated>2025-10-13T14:06:16.639Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Shubhojit Dasgupta — Independent API Architect</strong></p><figure><img alt="AI Driven Unified API Layer." src="https://cdn-images-1.medium.com/max/1024/1*0cLWljKkrcFrMgOWzL01FQ.png" /><figcaption>Unified API Layer Powered by AI</figcaption></figure><p>By teaming up <strong>WunderGraph</strong> with <strong>DreamFactory</strong>, the Organisation can create a super cool <strong>unified API management</strong> and integration layer! This layer will bring together authentication, access control, and observability from all sorts of different systems. WunderGraph’s API Gateway is awesome, and when you mix it with DreamFactory’s data source connectors and automation tools, one gets a workflow orchestration that’s smooth as butter with consistent policy enforcement, and a reliable way to abstract the backend’s complexity.</p><p>This integrated approach delivers a scalable, secure, and future-ready API platform that supports omnichannel service delivery, accelerates time-to-market for digital initiatives, and maintains robust governance over critical business workflows and data assets.</p><h3>Benefits for AI/ML Integration</h3><p>The Unified API Layer, powered by <strong>DreamFactory, WunderGraph</strong> and enhanced by the <strong>Kong AI Gateway</strong>, enables seamless integration and management of AI and ML capabilities across the organisation.</p><p><strong>DreamFactory</strong> and <strong>WunderGraph</strong> provide a <strong>unified access point</strong> to diverse data sources and services, while Kong AI Gateway governs &amp; secures the AI prompt layer to ensure security, compliance, and consistent performance.</p><p>Together, these technologies create a scalable and efficient foundation for developing, deploying, and leveraging <strong>AI-driven solutions</strong> that accelerate innovation and business value.</p><h3>How WunderGraph Helps</h3><p><strong>GraphQL Resolvers</strong> can be used to integrate <strong>AI/ML endpoints</strong> into the unified API. For example, a GraphQL query can be designed to fetch real-time traffic predictions:</p><pre>query {<br>  predictTraffic(location: &quot;XYZ&quot;) {<br>    trafficCongestionLevel<br>    accidentRisk<br>  }<br>}</pre><p><strong>WunderGraph</strong> allows you to expose these <strong>AI model predictions</strong> in a consistent API structure, ensuring that other services and apps can easily access and act on these predictions providing the following benefits.</p><p>● <strong>Data Accessibility</strong>: The Unified API Layer ensures that AI/ML models can easily access data from multiple sources, whether legacy systems, cloud databases, or real-time data streams.</p><p>● <strong>Real-Time AI Inference</strong>: By exposing AI/ML models through the Unified API, frontend applications can make real-time predictions and decisions based on AI models.</p><p>● <strong>Simplified AI Model Deployment</strong>: The Unified API abstracts the complexity of deploying and integrating AI models across different systems, making them accessible via a single API.</p><p>● <strong>Performance &amp; Scalability</strong>: Caching and API orchestration provided by WunderGraph ensure that AI models can scale efficiently, even when dealing with large data volumes and frequent requests.</p><p>● <strong>Unified Data Pipeline</strong>: The API layer can act as a unified data pipeline, ensuring that data from multiple sources is pre-processed and delivered in the right format to the AI/ML models.</p><h3>Simplified Deployment of AI/ML Models</h3><p>The Unified API Layer can act as a bridge between <strong>AI/ML model hosting platforms</strong> and <strong>operational systems</strong>. Whether your AI/ML models are deployed in the cloud (AWS Sagemaker, Google Cloud AI) or on-prem, the Unified API Layer abstracts the complexity and provides a single access point for all applications to interact with the models.</p><h4>Example: License Plate Recognition</h4><p>For instance, an AI-based <strong>license plate recognition (LPR)</strong> model hosted on a cloud service. The <strong>Unified API Layer</strong> can:</p><p>● Fetch license plate data from <strong>surveillance systems</strong> or vehicle registration databases.</p><p>● Send the data to the AI/ML model for recognition.</p><p>● Return the recognised license plate and associated vehicle information via the same unified API to frontend applications (such as law enforcement apps or toll management systems).</p><p>This <strong>abstracts away</strong> the underlying complexity of integrating the AI model, allowing the frontend systems to easily access AI-powered services.</p><h3>Unified Data Pipeline for AI/ML</h3><p>AI/ML models often need to access data in a pipeline format, where data from multiple sources is cleaned, processed, and prepared before being used for inference or analysis. The <strong>Unified API Layer</strong> can orchestrate this data flow, allowing the data to be sent to the AI/ML models in the required format.</p><h4>Example: Driver Behavior Analytics for Insurance</h4><p>An Organisation might want to work with insurance companies to provide <strong>driver behavior analytics</strong> for risk assessment.</p><p><strong>Unified API Layer</strong>:</p><p>● Aggregates data from <strong>driving history</strong> (from the vehicle database), <strong>accident history</strong>, and external factors (e.g., traffic, weather).</p><p>● Sends the aggregated data to an <strong>AI model</strong> for risk analysis.</p><p>● The AI model predicts the <strong>driver’s risk score</strong> (e.g., low-risk, high-risk).</p><p>● The score is returned to various stakeholders (insurance companies, law enforcement, etc.) through the <strong>unified API</strong>.</p><p>This ensures that the AI model gets consistent, relevant data and that the frontend systems can access predictions in real time, allowing insurers or authorities to make informed and timely decisions.</p><h3>Infrastructure &amp; Networking High-Level Overview</h3><figure><img alt="Networking and Infrastructure High-Level Architecture." src="https://cdn-images-1.medium.com/max/1024/1*qWZT2xkntlVUDdZ0CRbnHw.png" /><figcaption>Figure 1: Networking and Infrastructure High-Level Architecture.</figcaption></figure><h3>Benefits of GraphQL Based Unified API Layer</h3><p>WunderGraph sits on top of DreamFactory and <strong>composes</strong> these REST APIs into a <strong>Unified</strong> <strong>GraphQL schema</strong>. It allows you to merge multiple REST APIs, third-party services, or any other APIs into a single GraphQL endpoint. It abstracts the complexity of querying multiple services by letting clients use <strong>GraphQL</strong> to fetch data in a structured, efficient way with following benefits.</p><h4>Efficient Data Fetching</h4><ul><li>With GraphQL, clients can specify exactly what data they need, reducing over-fetching or under-fetching of data.</li><li>For example, instead of making multiple REST API calls to DreamFactory to fetch user data, order history, and shipping details, you can fetch all the necessary data in a single GraphQL query.</li></ul><h4>Flexible Queries</h4><p>Aggregate data from different sources (databases, external APIs, etc.) into one unified response. GraphQL’s query language is powerful and flexible, allowing clients to query exactly what they need from the unified API layer.</p><h4>Real-time Support</h4><p>WunderGraph supports <strong>real-time subscriptions</strong>, allowing you to turn REST APIs (which are inherently not real-time) into something you can subscribe to, providing real-time updates for clients.</p><h4>Example Workflow:</h4><ol><li>DreamFactory generates REST APIs for different data sources (e.g., a database with user data, a payment service, etc.).</li><li>WunderGraph composes these REST APIs and transforms them into a single GraphQL API.</li><li>Your application interacts with the GraphQL API, sending queries that internally get mapped to the corresponding REST APIs via WunderGraph.</li></ol><p><strong>GraphQL Query Example (Unified API Layer):</strong></p><pre>query {<br>  user(userId: 123) {<br>    name<br>    email<br>  }<br>  orderHistory(userId: 123) {<br>    orderId<br>    total<br>    items {<br>      name<br>      price<br>    }<br>  }<br>  processPayment(orderId: &quot;abc123&quot;, amount: 50.00) {<br>    status<br>    transactionId<br>  }<br>}</pre><p>This query fetches data from multiple sources (e.g., user information, order history, and processes a payment), but it appears as a single API endpoint thanks to the unified GraphQL layer created by WunderGraph. Behind the scenes, each part of the query might be hitting different REST endpoints generated by DreamFactory.</p><p>This approach will give you the flexibility, efficiency, and real-time capabilities of GraphQL while still leveraging DreamFactory’s ability to expose backend services as REST APIs.</p><h3>Integrated Observability &amp; Monitoring</h3><figure><img alt="Grafana Stack Observability &amp; Monitoring Platform Architecture." src="https://cdn-images-1.medium.com/max/1024/1*digwffTrGkI_CX2D7y2tNw.png" /><figcaption>Figure 2: Grafana Stack Observability &amp; Monitoring High-Level Platform Architecture</figcaption></figure><p>WunderGraph supports OpenTelemetry out of the box. OpenTelemetry is a collection of tools, APIs, and SDKs used to instrument, generate, collect, and export telemetry data (metrics, logs, and traces) for analysis to understand your APIs performance and behavior. With the help of OpenTelemetry, you can monitor your WunderGraph nodes and get a better understanding of your application’s performance. It instruments all outgoing HTTP requests and inner service calls with OpenTelemetry.</p><p>WunderGraph supports OpenTelemetry backend that supports the OTLP http protocol. One can also use the <a href="https://opentelemetry.io/docs/collector/"><strong>OpenTelemetry Collector </strong></a>to export traces to any other backend that is supported by the collector.</p><h4>Grafana Loki</h4><p>Grafana Loki collects logs independently of the built-in Prometheus exporter. Here’s how the integration typically works:</p><p><strong>Log Shipping</strong>:</p><ul><li><strong>WunderGraph</strong> itself doesn’t directly send logs to Loki. Instead, you need to set up log shipping in your application.</li><li>Common log shippers include tools like <strong>Fluentd</strong>, <strong>Fluent Bit</strong>, <strong>Logstash</strong>, or <strong>Promtail</strong> (which is specifically designed to work with Loki).</li></ul><p><strong>Using Promtail</strong>:</p><ul><li>If you choose to use <strong>Promtail</strong>, you can configure it to watch log files generated by your application (including those from WunderGraph).</li><li>Promtail reads the logs and sends them to your Loki instance. You can specify various configurations, such as how to parse the logs and which labels to apply.</li></ul><p><strong>Direct Integration</strong>:</p><ul><li>You can also directly instrument your application to send logs to Loki using the Loki client libraries available in various programming languages.</li><li>This method allows for more customised log handling and flexibility.</li></ul><p><strong>Grafana Setup:</strong></p><ul><li>After logs are collected and sent to Loki, you can then configure Grafana Alloy to use Loki as a data source.</li><li>You can create dashboards and queries in Grafana to visualize the logs alongside metrics from Prometheus and traces from Jaeger.</li></ul><p>Grafana Loki collects logs from your applications through log shippers or client libraries, not directly through the Prometheus exporter. The logs can then be visualized in Grafana, providing a comprehensive observability solution alongside metrics and traces.</p><h4>Grafana Alloy</h4><p><strong>Grafana Alloy</strong> is designed to provide an integrated observability experience, it pulls the telemetry data from Prometheus Server, Grafana Loki and OpenTelemetry collectors like Jaeger and sends them to Grafana user interface (UI) for visualisation and dashboard creation.</p><p><strong>Grafana Alloy</strong> acts as a bridge, allowing you to configure data sources that Grafana can query. You can set up Grafana to pull data from various telemetry sources, including:</p><ul><li><strong>Prometheus</strong>: For metrics collection.</li><li><strong>Jaeger</strong>: For distributed tracing data.</li><li><strong>Zipkin</strong>: For tracing data.</li><li><strong>Loki</strong>: For logs.</li></ul><p><strong>Grafana Alloy</strong> aims to unify observability across your applications, aggregating metrics, logs, and traces from various sources (like Prometheus, Loki, and Jaeger) in one platform. It uses the Grafana UI, which is a powerful tool for creating custom dashboards, charts, and graphs based on the collected telemetry data. While it streamlines data collection and organisation, users still need to interact with the Grafana UI to create visualisations, alerts, and dashboards.</p><h4>Grafana</h4><p><strong>Grafana</strong>, allows you to create dashboards that visualise the telemetry data. This includes:</p><ul><li>Graphs and charts for metrics like response times, request counts, and error rates.</li><li>Trace views to visualise the flow of requests and understand performance bottlenecks.</li><li>Logs for real-time monitoring and troubleshooting.</li></ul><p>With <strong>Grafana</strong> set up alerts based on the telemetry data to notify your Teams of potential issues, such as high error rates or latency spikes.</p><h3>API Led AI Experience</h3><p>The mainstream availability of generative AI (genAI) technologies, large language models (LLM), and vector databases (DBs) has created an unprecedented race for AI adoption. AI’s rapid evolution and heavy reliance on data introduces new complexities that must be managed as increasing pressure mounts to leverage AI.</p><p><strong>Kong AI Gateway</strong> facilitates an Organisation to integrate AI into their Applications with greater Ease, Security, and Standardisation. This simplifies the process of <strong>Connecting</strong>, <strong>Managing</strong>, and <strong>Securing</strong> access to multiple LLMs without needing to write any code.</p><figure><img alt="Kong AI Gateway: Securing and Orchestrating Intelligent Workflows Between MCP Clients, AI Agents, and MCP Servers." src="https://cdn-images-1.medium.com/max/1024/1*o13wAeU7TE7fUMppdgIt4w.avif" /><figcaption><strong>Kong AI Gateway</strong>: Securing and Orchestrating Intelligent Workflows Between AI Client and MCP Servers</figcaption></figure><figure><img alt="AI Transformation with Kong AI Gateway." src="https://cdn-images-1.medium.com/max/1024/1*cA2gpanqYnP-WB7PNs-NEQ.png" /><figcaption>Figure 3: Kong AI Gateway Key Benefits</figcaption></figure><h4>No AI Without API</h4><figure><img alt="AI models managed before Kong AI Gateway ." src="https://cdn-images-1.medium.com/max/1024/1*QWoIhQp-0bOLdrIQob-KNw.png" /><figcaption>Figure 4: Applications Consuming AI LLM Models Before Kong AI Gateway</figcaption></figure><h4>Kong AI Gateway</h4><figure><img alt="Communications managed between Applications and AI models after incorporating Kong AI Gateway." src="https://cdn-images-1.medium.com/max/1024/1*8EMDpKxAVxmRSOPYkMd8Qg.png" /><figcaption>Figure 5: Applications Consuming AI LLM Models with Kong AI Gateway</figcaption></figure><p><strong>Kong AI Gateway</strong> serves as a centralised control layer connecting enterprise applications with multiple large language models (LLMs).</p><p>As an intelligent intermediary, <strong>Kong AI Gateway</strong> enables applications to consume AI capabilities securely and efficiently through built-in features such as AI security, AI prompt firewalling, context management, AI model token-based rate limiting, and multi-LLM endpoint orchestration.</p><p>It <strong>abstracts</strong> the complexity of prompt management, credentials, logging, and metrics, allowing developers to focus on business logic while ensuring governance, reliability, and scalability in AI-driven workflows. This unified approach helps organisations standardise &amp; optimise their AI interactions across diverse AI-driven models and environments.</p><h4>Multi LLM Strategy</h4><figure><img alt="Multi-LLM Strategy with Kong AI Gateway." src="https://cdn-images-1.medium.com/max/1024/1*JAxHw3jXbKrFLgeh6I-qAQ.png" /><figcaption>Figure 6: Multi-LLM Strategy with Kong AI Gateway</figcaption></figure><p>AI LLM Models are trained via APIs managed and governed via Kong AI Gateway, facilitating in developing a Multi LLM strategy for Organisations with Compliance and AI Governance.</p><p>Kong AI Gateway’s <strong>multi-LLM strategy</strong> enables organisations to connect their applications to multiple large language models simultaneously, choosing the best model for each task based on factors like speed, cost, reliability, or topic expertise. Through advanced features such as semantic routing, prompt caching, and load balancing, the AI Gateway automatically directs AI requests to the most suitable LLM, ensuring optimal performance and redundancy if one model becomes unavailable. This unified approach not only increases resiliency and flexibility but also allows seamless scaling and governance across complex AI-driven workflows.</p><h3>Conclusion</h3><p>This is a two part blog, where in this <a href="https://medium.com/@shubhojit.dasgupta/ai-driven-unified-api-layer-d6d14a6da5d4"><strong>part</strong></a> we covered the following;</p><p>● AI/ML integration with Unified API Layer generated using WunderGraph and DreamFactory significantly improving the operations of AI models.</p><p>● Exposing <strong>AI model predictions</strong> in a consistent API structure, using <strong>WunderGraph </strong>with Real-Time AI Inference based on AI Models.</p><p>● Deployment of AI/ML Model with performance and scalability simplified using Unified Data Pipeline orchestrated through the Unified API Layer.</p><p>● High-Level Overview of Networking and Infrastructure Architecture.</p><p>● Benefits of GraphQL Based Unified API Layer.</p><p>● Integrated Observability &amp; Monitoring using Grafana Tech Stack.</p><p>● API<strong> </strong>led AI experiences via Kong AI Gateway facilitating an Organisation to integrate AI into their Applications with greater Ease, Security, and Standardisation and Compliance with Multi-LLM strategy.</p><p>Visit the <a href="https://medium.com/@shubhojit.dasgupta/enhanced-omnichannel-experience-with-unified-api-layer-1cabff44e895"><strong>previous blog</strong></a><strong> </strong>to understand the solution for a robust, fully-integrated Unified API Layer that acts as an abstraction between multiple APIs, omni-channel systems, modern/legacy systems, databases, and applications.</p><p>In the <a href="https://medium.com/@shubhojit.dasgupta/enhanced-omnichannel-experience-with-unified-api-layer-1cabff44e895"><strong>previous blog</strong></a><strong> </strong>we explored different platforms and High-Level Architecture combining strengths of DreamFactory &amp; WunderGraph supporting for an omnichannel experience by delivering seamless, integrated service across multiple channels such as mobile apps, web platforms, kiosks, and call centres.</p><h3>Summary</h3><p>AI Driven Unified API architecture serves various business needs for an Organisation, providing unified API management Platform to interact with both legacy systems (via REST APIs) and modern services (via Unified API Layer), while maintaining performance and security.</p><p>The Architecture outlines a Scalable, Modular Architecture designed to optimise API consumption, Orchestration, Aggregation, Federation and REST API generation while maintaining clear separation between unified API Orchestration and Integration Layer (WunderGraph) and REST APIs generation layer (DreamFactory).</p><p>AI and APIs are revolutionising industries. While challenges exist, the potential for innovation and discovery is limitless. Kong’s AI capabilities, along with WunderGraph and DreamFactory integration, offer solutions for organisations that adapt, harness AI’s creative potential, and leverage APIs to explore new possibilities.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d6d14a6da5d4" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Enhanced Omnichannel Experience with Unified API Layer]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/enhanced-omnichannel-experience-with-unified-api-layer-1cabff44e895?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/1cabff44e895</guid>
            <category><![CDATA[dreamfactory]]></category>
            <category><![CDATA[graphql-api]]></category>
            <category><![CDATA[unified-api]]></category>
            <category><![CDATA[wundergraph]]></category>
            <category><![CDATA[kong-gateway]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Mon, 13 Oct 2025 12:08:20 GMT</pubDate>
            <atom:updated>2025-10-13T14:01:33.324Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Shubhojit Dasgupta — Independent API Architect</strong></p><figure><img alt="Unified API Layer for Great Omnichannel Experience." src="https://cdn-images-1.medium.com/max/1024/1*Fyr1i-uhf0Ivv64I4qjhOg.png" /><figcaption>Seamless Omnichannel Experience Powered by API Platforms</figcaption></figure><h3>Solution Overview</h3><p>A <strong>robust fully integrated</strong> unified API layer serves as an abstraction that connects multiple APIs, omnichannel systems, modern and legacy systems, on-premises and cloud databases, and the applications that directly consume them. This layer provides a single point of access and a standardised interface for various services. The objective is to streamline and simplify developer interactions with multiple APIs, irrespective of their complexity or implementation differences.</p><h3>Proposed Platforms &amp; Architecture</h3><p>The solution will feature a <strong>Vendor-Agnostic Unified API Layer</strong> that combines the strengths of <strong>DreamFactory</strong> and <strong>WunderGraph</strong>. These <strong>Low-Code</strong> Open-Source Platforms facilitate seamless API generation, loosely coupled orchestration and minimal code integration. The solution will enable efficient API creation from multiple data sources and advanced API orchestration for Microservices, Legacy Systems, Databases, IoT devices and external RESTful APIs.</p><p>Once API Orchestration/Integration and REST API layers, are respectively generated and stable, then Kong AI Gateway integrates in-between these layers effectively managing and governing AI prompts from Unified API System powered by <strong>WunderGraph</strong> through API Orchestration/Integration Layer, with the REST API Layer generated using <strong>DreamFactory.</strong></p><p>A <strong>Robust</strong> and <strong>Powerful</strong> <strong>Low-Code</strong> <strong>Open-Source</strong> <strong>solution</strong> which streamlines backend API generation and orchestration, providing a scalable, flexible, and secured standardised interface for developers and systems to interact directly with diverse Data Sources, whether on-prem or hosted on Cloud.</p><h4>What is DreamFactory?</h4><p><strong>DreamFactory</strong> is an Open-Source REST APIs generation solution, best known for its ability to automatically generate, secure and documented APIs for databases like Microsoft SQL Server, MySQL, Snowflake, PostgreSQL, Oracle, MongoDB, Time-Series Databases and more. It is built on top of the Laravel framework, and includes a convenient web-based administration client. DreamFactory does the following;</p><ul><li><a href="http://guide.dreamfactory.com/docs/chapter03.html#generating-a-mysql-backed-api">Generate</a> powerful, reusable, documented REST APIs for SQL and NoSQL databases, files, email, push notifications and more in seconds.</li><li><a href="https://guide.dreamfactory.com/docs/integrating-business-logic-into-your-apis/">It uses the PHP, Python, and NodeJS scripting languages</a> to easily customize REST API behavior at any endpoint, for both API requests and API responses.</li><li>It <a href="http://guide.dreamfactory.com/docs/chapter03.html#creating-a-role">secures every API endpoint</a> with user management, Token-based authentication, role-based access control, OAuth 2.0, OpenID Connect and API Keys with basic Rate Limiting features. For advanced security features one would have to upgrade it later to an Enterprise version.</li></ul><h4>DreamFactory High-Level Architecture</h4><figure><img alt="High-Level Architectural Overview of DreamFactory." src="https://cdn-images-1.medium.com/max/979/0*hjeyugBCDryitPjl.png" /><figcaption>Figure 1: High-Level Architectural Overview of DreamFactory</figcaption></figure><h4>DreamFactory Components</h4><p>The DreamFactory application can be divided into several operational components. While these components are logical and do not necessarily represent the code structure itself, they are useful in discussing the subsystems and functionality of the application, as well as the anatomy of the API call later.</p><figure><img alt="Logical Components in DreamFactory." src="https://cdn-images-1.medium.com/max/1024/1*kceMRnuDC_Z0oLC_GRczuw.png" /><figcaption>Figure 2: DreamFactory Operational Components</figcaption></figure><h4>What is WunderGraph?</h4><p><strong>WunderGraph</strong> is a <strong>Backend for Frontend (BFF) Framework</strong> designed to <strong>optimize</strong> Developer Workflows through API Composition. At its core, WunderGraph combines two patterns, API Gateway and <strong>Backends for Frontends</strong> providing <strong>Single-purpose Edge Services</strong> for UIs and external parties with the concept of a package manager, making API composition simple.</p><h4>API Composition</h4><p><strong>API Composition</strong> is a new pattern that allows one to interact with a heterogeneous set of APIs as if they were a single unified API. This not only eliminates a lot of glue code, but also allows you to reason about the API Dependencies of an application. <strong>Do you actually know what APIs and Services your application depends on?</strong> <strong>WunderGraph</strong> can easily answer this question for you, and even gives you analytics and observability into Organisation’s APIs and Endpoints that are consumed by all its applications and backend-services and also the quality of service all API dependencies provide.</p><h4>WunderGraph High-Level Architecture</h4><figure><img alt="High-Level Architecture of WunderGraph." src="https://cdn-images-1.medium.com/max/1024/1*ClQNffUyZu1J0LQ-q8_GSw.png" /><figcaption>Figure 3: Wundergraph High-Level Architecture for a Unified API System</figcaption></figure><h4>WunderGraph Benefits</h4><p>● WunderGraph is an API composition platform focused on GraphQL. It enables developers to compose and unify multiple APIs (REST, GraphQL, databases, etc.) into a single unified GraphQL API.</p><p>● It abstracts complexity by providing a single interface for developers to query multiple services, which are composed behind the scenes.</p><p>● Offers real-time data, caching, and built-in security features.</p><h4>WunderGraph and DreamFactory Working Together</h4><ol><li><strong>DreamFactory</strong> quickly generates and exposes APIs (REST, SOAP, or GraphQL) from a variety of backends, like databases or external services as REST APIs with well defined OpenAPI specifications.</li><li><strong>WunderGraph</strong> Orchestrates and Integrates on top of DreamFactory to <strong>compose</strong> these APIs (as well as other external APIs) into a <strong>single GraphQL endpoint</strong>. This GraphQL layer acts as a unified API layer, providing access to all the underlying APIs exposed by DreamFactory or any other external and backend services.</li></ol><p>This gives the <strong>REST</strong> <strong>APIs generation</strong> power of DreamFactory and the <strong>API composition, aggregation </strong>and <strong>federation</strong> capabilities of WunderGraph.</p><h3>Unified API System with WunderGraph</h3><h4>Virtual Graph</h4><p>The Virtual Graph is a concept in WunderGraph. It’s the idea of combining multiple GraphQL Schemas into a single, unified, schema. As we’re using a JSON RPC compiler instead of directly exposing the GraphQL, we’re calling this concept the “Virtual Graph”.</p><p>The Virtual Graph is only really available during development. But when deploying to production, the GraphQL to JSON RPC compiler will automatically turn all defined GraphQL Operations into JSON RPC Endpoints. That’s why this Graph really only exists virtually, hence the name.</p><p>What’s so powerful about having a concept like the Virtual Graph is that it enables you to think explicitly about APIs as dependencies. The Virtual Graph is your gateway to the other APIs you want to use. With this idea in mind, you can understand GraphQL as the language to “program” with APIs.</p><p>Add API dependencies to your WunderGraph application and use GraphQL to define your API surface. The Virtual Graph allows you to meta-program your APIs with GraphQL. The artifact will be an API Gateway and one or more generated clients, speaking JSON RPC over HTTP between the them.</p><h4>WunderGraph Server</h4><p>WunderGraph Server is the heart of the WunderGraph framework. It’s the API Gateway of the stack and written in Golang / Go. The Gateway is highly optimized for performance and scalability. When starting the WunderGraph server, it will use our GraphQL to JSON RPC compiler and turn all the GraphQL Operations you’ve defined into JSON RPC calls. All of this happens at deployment time, so we’re actually removing GraphQL from the runtime at all.</p><p>In production environment, the Gateway is handling requests by calling the pre-compiled, pre-optimized JSON RPC calls. All aspects such as lexing, parsing and validating GraphQL Operations is handled during the deployment, not during the request execution.</p><p>Architecting WunderGraph this way makes it very efficient and secure. It’s possible because GraphQL Operations usually don’t change at runtime. So, if one is not changing Operations at runtime, one can turn GraphQL into a compile-time problem, removing it from the runtime entirely.</p><h4>High-Level Unified API Layer Architecture</h4><figure><img alt="High-Level Unified API Layer Architecture." src="https://cdn-images-1.medium.com/max/944/1*5z2xQ723Fj1yy3B29z6Fyw.png" /><figcaption>Figure 4: High-Level Architecture for a Unified API Layer</figcaption></figure><h4>WunderGraph Client</h4><p>WunderGraph is not just a framework to generate an API Gateway/Backend for Frontend (BFF). It also generate clients from the same configuration, giving organisations a full end-to-end solution, with no additional tools required. All configurations are in <strong>wundergraph.config.ts</strong> file. Alongside the backend configuration, one can define what templates to use to generate the client.</p><p>One good example of how a client could look like is TypeScript and Next.js. As Wundergraph’s monorepo is open source, all templates are available for use, and one can easily create their own.</p><p>The generated client is based on the Wundergraph RPC Protocol. This protocol defines how WunderGraph server and the generated client communicate. The protocol works over HTTP/1.1 and HTTP/2, supports Queries, Mutations, Subscriptions, Live-Queries, authentication and file uploads.</p><p>Client and server speak JSON RPC over HTTP, defined by the WunderGraph RPC Protocol. If a client wants to execute an Operation, it calls an Endpoint on the API Gateway, which will then execute the pre-compiled Operation against the Virtual Graph. Both request and response can be manipulated using hooks.</p><h4>GraphQL Proxy Layer in WunderGraph</h4><p>The <strong>built-in GraphQL Proxy Layer</strong> in <strong>WunderGraph</strong> provides a unique mechanism to handle both <strong>REST API requests</strong> and <strong>GraphQL requests</strong> from clients, offering a <strong>unified API platform</strong>.</p><p><strong>Clients Sending REST API Requests: </strong>WunderGraph can act as a REST-to-GraphQL proxy, allowing REST API clients to interact with backend GraphQL or REST APIs.</p><p>● The client sends a REST API request to the WunderGraph server.<strong> </strong>The WunderGraph server receives the REST request, determines the associated operation, and forwards the request to the relevant backend service. This service could be a GraphQL API, REST API, or another type of data source.</p><p>● The GraphQL Proxy Layer in WunderGraph can transform the REST request into a GraphQL query if necessary, interacting with backend GraphQL services.</p><p>● Example: A REST request to /users/123 could be transformed into a GraphQL query like { user(id: “123”) { name, email } }.</p><p>● WunderGraph aggregates the response (either from a GraphQL or REST backend) and formats it back into a REST response format.</p><p>The client receives the REST API response as if they were calling a native REST endpoint, even if the backend services were GraphQL.</p><h4>REST API Workflow with WunderGraph Key Features</h4><p>● <strong>REST-to-GraphQL transformation</strong>: Clients can send REST requests, and WunderGraph handles the transformation into GraphQL queries when needed.</p><p>● <strong>Aggregation</strong>: WunderGraph can aggregate data from multiple sources (both REST and GraphQL) and present a single, unified REST response.</p><p>● <strong>Authentication</strong>: WunderGraph handles any required authentication (e.g., OAuth tokens) before forwarding the requests to backend services.</p><p><strong>Clients Sending GraphQL Requests:</strong> clients that prefer to use <strong>GraphQL</strong>, WunderGraph serves as a <strong>GraphQL proxy</strong>, enabling the client to query and interact with multiple backend services through a unified GraphQL interface.</p><p>● <strong>Client sends a GraphQL query</strong> to the WunderGraph server.</p><p>● The <strong>GraphQL Proxy Layer</strong> processes the query and maps it to the appropriate backend APIs (REST or GraphQL).</p><p>● If the backend service is a REST API, the GraphQL Proxy Layer converts the GraphQL query into a REST request.</p><ul><li>Example: A GraphQL query like { user(id: “123”) { name, email } } could be transformed into REST request like /users/123.</li><li>WunderGraph forwards the request to the backend service, collects the response, and formats it according to the GraphQL specification.</li></ul><p>● <strong>Client receives the GraphQL response</strong> in the standard format, even if some data originated from REST APIs.</p><h4>GraphQL Workflow with WunderGraph Key Features</h4><p>● <strong>Unified Data Access:</strong> WunderGraph can interact with multiple backend services (both REST and GraphQL) and expose them through a single GraphQL schema.</p><p>● <strong>Schema Stitching:</strong> WunderGraph can stitch multiple GraphQL schemas together, allowing clients to query across various services in one request.</p><p>● <strong>Caching and Optimisations:</strong> WunderGraph can cache results for GraphQL queries, improving performance for repeated requests.</p><p>REST clients can interact with GraphQL backends through WunderGraph’s <strong>GraphQL Proxy Layer</strong>, which transforms REST requests into GraphQL queries.</p><p>GraphQL clients can interact with REST backends by having their GraphQL queries transformed into REST API calls.</p><p>WunderGraph seamlessly handles the transformations, aggregations, and response formatting, making it an ideal solution for environments where both REST and GraphQL are used. This approach enables flexibility for clients using different API paradigms, while still benefiting from the powerful features of <strong>WunderGraph’s Unified API Layer</strong>.</p><h3>High Availability of REST APIs Generation Layer</h3><figure><img alt="DreamFactory Load Balanced HA Environment." src="https://cdn-images-1.medium.com/max/1024/1*hLM0Y3DXXoVfSNOPd27avw.png" /><figcaption>Figure 5: High Availability and Reliability of REST APIs Generation Layer</figcaption></figure><h4>Unified Caching Mechanism</h4><p><strong>GraphQL Proxy </strong>in WunderGraph<strong> </strong>is designed primarily to handle GraphQL API requests, it can also cache <strong>REST API requests</strong>. Since the proxy layer is part of the <strong>Unified API Layer</strong>, it has access to all incoming requests — whether REST APIs or GraphQL.</p><p>When a REST API request is received, the GraphQL Proxy Layer first checks if a cached response for that specific request exists. If the response is cached, it is served directly from the caching service without hitting the backend APIs and DreamFactory’s REST APIs Generation Layer. If not, the proxy forwards the request to the backend REST service, retrieves the response, and caches it for future requests.</p><p>The caching service in the <strong>Unified API Layer</strong>, allows to handle both GraphQL and REST requests efficiently. The WunderGraph Server which is also a Gateway Caches all API responses automatically and apply the necessary headers, including <strong>ETags</strong> for efficient content revalidation. The server will cache the response in memory and compute an ETag for the response, which will be sent to the client along with the response. On subsequent requests, the client will automatically attach the ETag to the request, which is the default behaviour of the browser. If the client cache is stale, but the <strong>ETag</strong> still matches, the server will respond with a 304 Not Modified, sending as little data as possible.</p><h4>Process Flow Between WunderGraph &amp; Middleware Systems</h4><p>Applications consuming and interacting with APIs exposed from the Unified API layer don’t do so directly instead they communicate bidirectionally with the WunderGraph Client without being concerned about protocols used to orchestrate the Unified API Layer with all complexities abstracted by WunderGraph Server and the WunderGraph’s generated client.</p><h4>Data Source Configuration</h4><p>Let us add two APIs to our Application.</p><pre>// wundergraph.config.ts<br>const weather = introspect.graphql({<br>    apiNamespace: &#39;weather&#39;,<br>    url: &#39;https://weather-api.wundergraph.com/&#39;,<br>  });<br>  <br>  const countries = introspect.graphql({<br>    apiNamespace: &#39;countries&#39;,<br>    url: &#39;https://countries.trevorblades.com/&#39;,<br>  });<br>  <br>  configureWunderGraphApplication({<br>    apis: [weather, countries],<br>  });</pre><h4>Operation Definition</h4><p>Next, we’ll define a GraphQL Operation that uses the <strong>Cross API JOIN</strong> feature of <strong>WunderGraph</strong>. It takes away a lot of complexity, which is also quite handy to illustrate the different capabilities of WunderGraph.</p><pre># operations/Weather.graphql<br>query (<br>  $continent: String!<br>  # the @internal directive removes the $capital variable from the public API<br>  # this means, the user can&#39;t set it manually<br>  # this variable is our JOIN key<br>  $capital: String! @internal<br>) {<br>  countries: countries_countries(filter: { continent: { eq: $continent } }) {<br>    code<br>    name<br>    # using the @export directive, we can export the value of the field `capital` into the JOIN key ($capital)<br>    capital @export(as: &quot;capital&quot;)<br>    # the _join field returns the type Query!<br>    # it exists on every object type so you can everywhere in your Query documents<br>    # with the @transform directive, we can transform the response<br>    weather: _join @transform(get: &quot;weather_getCityByName.weather&quot;) {<br>      # once we&#39;re inside the _join field, we can use the $capital variable to join the weather API<br>      weather_getCityByName(name: $capital) {<br>        weather {<br>          temperature {<br>            max<br>          }<br>          summary {<br>            title<br>            description<br>          }<br>        }<br>      }<br>    }<br>  }<br>}</pre><h4>WunderGraph Example Sequence Diagram</h4><figure><img alt="Sequence Diagram depicting API Orchestration via WunderGraph Server." src="https://cdn-images-1.medium.com/max/1024/1*l_i91jbRvZ_ql0omJp2uRQ.png" /><figcaption>Figure 6: Sequence Diagram for API Orchestration between two APIs via WunderGraph Server</figcaption></figure><h4>Scalable and Secure System</h4><p>When defining GraphQL Operations using WunderGraph, it automatically generates a JSON REST API for you. Additionally, it generates a 100% typesafe client. This means, you’re getting the same developer experience as if you were using a standard GraphQL API, but without the tradeoffs in terms of security and scalability.</p><p>If your DreamFactory instance is deployed on-prem but your databases are in cloud, you can securely configure connections between them using VPNs, <strong>VPC Peering</strong>, or <strong>SSL/TLS encryption</strong> to ensure secure communication between your on-prem DreamFactory and cloud-hosted resources. This enables you to manage both <strong>on-premise</strong> and <strong>cloud-based</strong> systems under a unified API framework without having to manually develop REST APIs for each data source. Open-Source DreamFactory provides the following security features for your REST APIs Generation Layer.</p><p>● <strong>Role-Based Access Control (RBAC)</strong> with fine-grained permissions.</p><p>● <strong>API Key Authentication</strong> for controlling access to APIs.</p><p>● <strong>User Authentication</strong> via local credentials, OAuth providers &amp; JWT-based sessions.</p><p>● <strong>CORS Support</strong> to prevent unauthorized domains from accessing APIs.</p><p>● <strong>SSL/TLS Encryption</strong> to secure API communications.</p><p>● <strong>Basic Rate Limiting</strong> for managing API request loads.</p><p>● <strong>Custom Scripting</strong> for additional security logic.</p><h3>Unified API/Orchestration Layer &amp; REST API Generation Layer Decoupling</h3><p>Decoupling the <strong>Unified API &amp; Orchestration Layer</strong> (built using <strong>WunderGraph Open Source</strong>) and the <strong>REST API Generation Layer</strong> (from <strong>DreamFactory Open Source</strong>) involves creating clear boundaries between the two layers in terms of responsibility, communication, and management. Here’s how this can be achieved:</p><figure><img alt="Unified Open API Schema Powered by WunderGraph." src="https://cdn-images-1.medium.com/max/1024/1*u2zQ_6aOo3U-nGlxqr-Pvw.png" /><figcaption>Unified API GraphQL based Schema Powered by WunderGraph</figcaption></figure><h4>● Unified API &amp; Orchestration Layer (WunderGraph):</h4><ul><li><strong>Primary Role</strong>: Orchestrates and unifies access to various APIs (REST, GraphQL, databases) by acting as a single point of entry for clients. It transforms, proxies, and handles both REST and GraphQL requests, including aggregation, caching, and security.</li><li><strong>REST-to-GraphQL Transformation</strong>: WunderGraph transforms REST APIs into GraphQL queries if needed and can call multiple services within a single query.</li><li><strong>Orchestration</strong>: Coordinates calls to multiple APIs and handles complex workflows (e.g., aggregating data from different sources).</li></ul><h4>● REST API Generation Layer (DreamFactory):</h4><ul><li><strong>Primary Role</strong>: Exposes backend services, databases, or other systems as <strong>REST APIs</strong>. It generates REST endpoints for various data sources (e.g., SQL databases, NoSQL databases, file storage).</li><li><strong>Focus on API Generation</strong>: DreamFactory’s focus is on creating REST APIs automatically from a variety of sources, and it also manages API documentation and access control for those APIs.</li></ul><h4>● Loose Coupling through API Contracts:</h4><ul><li>The communication between the <strong>Unified API Layer</strong> (WunderGraph) and the <strong>REST API Generation Layer</strong> (DreamFactory) happens over well-defined REST API contracts. WunderGraph can consume REST APIs generated by DreamFactory as if they were any external service.</li><li><strong>Contract-based Communication</strong>: The two systems are decoupled through API contracts (OpenAPI specs or similar). DreamFactory exposes APIs, and WunderGraph consumes them based on the provided contract, with no direct dependencies on the internal workings of DreamFactory.</li></ul><h4>● Communication Over HTTP(S)</h4><p>Both layers communicate over standard HTTP(S) protocols, typically via REST APIs. This allows for:</p><ul><li><strong>Clear Separation</strong>: Each layer operates independently, and they only communicate through well-defined API calls.</li><li><strong>Standard Interfaces</strong>: Since the REST APIs follow common protocols and standards, there’s no need for deep integration, and either layer can be modified or replaced without impacting the other.</li></ul><h4>● Autonomous Lifecycles</h4><ul><li><strong>Independent Deployment</strong>: WunderGraph and DreamFactory can be deployed separately, each with its own lifecycle. You can deploy and scale each independently, manage their performance, and update them without affecting the other.</li><li><strong>Version Control</strong>: Each layer can be updated independently (e.g., updating the DreamFactory REST APIs without affecting the WunderGraph orchestration layer).</li></ul><h4>● Decoupled Authentication and Authorization</h4><ul><li>Both <strong>WunderGraph</strong> and <strong>DreamFactory</strong> handle their own authentication and authorization, but they can be integrated loosely via token-based mechanisms.</li><li>For instance, <strong>DreamFactory</strong> might handle API key, OAuth, or JWT-based authentication for the REST APIs it generates, while <strong>WunderGraph</strong> manages authentication for its unified layer, using those tokens when communicating with DreamFactory.</li></ul><h4>● Abstracting Business Logic in WunderGraph</h4><ul><li><strong>Business Logic in WunderGraph</strong>: WunderGraph handles the orchestration logic. It consumes DreamFactory’s REST APIs but can also call other services, aggregate data, and apply business rules without requiring changes in DreamFactory.</li><li><strong>DreamFactory Focus</strong>: DreamFactory remains focused on generating APIs and connecting to backend data sources. It doesn’t need to be aware of how WunderGraph orchestrates multiple APIs or combines data from other sources.</li></ul><h4>● Flexible, Extensible Architecture</h4><ul><li><strong>Replaceability</strong>: Since WunderGraph and DreamFactory are decoupled via standard APIs, you could theoretically replace DreamFactory with another API generation tool (e.g., a custom-built solution or another REST generator) without heavily impacting the WunderGraph orchestration.</li><li><strong>Extensibility</strong>: You could add other systems to either layer without needing to modify the core logic of the other. For instance, you can introduce additional REST or GraphQL services into the Unified API Layer without altering DreamFactory’s REST generation.</li></ul><h3>Error Handling and Caching at the Unified API Layer</h3><p>WunderGraph can handle <strong>error management</strong>, <strong>retry policies</strong>, and <strong>caching</strong> for the APIs generated by DreamFactory. This ensures the DreamFactory APIs are decoupled from the performance or error-handling logic, and those aspects are managed by WunderGraph’s orchestration capabilities.</p><h3>Decoupled Architecture</h3><p>In the architecture diagram:</p><ul><li>The <strong>Unified API &amp; Orchestration Layer</strong> (WunderGraph) would communicate with the <strong>REST API Generation Layer</strong> (DreamFactory) through a <strong>double arrow</strong> indicating API communication.</li><li>The <strong>arrows</strong> represent API requests and responses over HTTP(S) and show the clear separation between the two layers.</li><li>Each layer has its own box with a clear boundary, indicating they are separate systems, but connected via standard REST API calls.</li></ul><h4>Example Architecture Flow:</h4><ol><li><strong>DreamFactory</strong> generates REST APIs from a database (e.g., GET /users).</li><li><strong>WunderGraph</strong> calls this REST API to retrieve the user data and may aggregate it with data from other sources (e.g., a GraphQL API for profile data).</li><li>WunderGraph exposes the aggregated data as either a <strong>GraphQL API</strong> or a <strong>REST API</strong> to the client.</li><li><strong>Both systems are decoupled</strong>: Changes in one layer do not directly impact the other.</li></ol><p>The <strong>Unified API Layer (WunderGraph)</strong> and the <strong>REST API Generation Layer (DreamFactory)</strong> are decoupled by:</p><ul><li>Separating their roles and responsibilities.</li><li>Communicating via standard REST APIs (using HTTP(S) and API contracts).</li><li>Being deployed independently and managing their own lifecycles.</li><li>Handling authentication and security independently but integrating token-based communication.</li><li>Allowing flexible integration and extension without tightly coupling both systems.</li></ul><p>This <strong>decoupling</strong> makes the Architecture <strong>Scalable</strong>, <strong>Maintainable</strong>, and <strong>Adaptable</strong> to changes in either layer.</p><h3>Omnichannel Experience &amp; API Modernisation</h3><p>Designing the <strong>Unified API Layer</strong> using <strong>DreamFactory</strong> and <strong>WunderGraph</strong> for large Organisations<strong> </strong>offers significant benefits for both <strong>omnichannel experience</strong> and <strong>API modernisation</strong>.</p><h4>Omnichannel Experience</h4><p>An <strong>omnichannel experience</strong> means delivering a seamless, integrated service across multiple channels, such as mobile apps, web platforms, kiosks, and call centers. The <strong>Unified API Layer</strong> acts as a central hub that allows all these channels to interact with the same data and services, ensuring consistency and accessibility.</p><h4>Example: Vehicle Registration Service Across Multiple Channels</h4><p>A <strong>Vehicle Registration service</strong> where citizens can register their vehicles via</p><ul><li><strong>Mobile App</strong></li><li><strong>Web Portal</strong></li><li><strong>Kiosk at Transport Offices</strong></li><li><strong>Customer Support Center</strong></li></ul><h4>How the Unified API Layer Supports Omnichannel:</h4><ul><li><strong>DreamFactory</strong> connects to multiple backend databases (like MySQL or PostgreSQL for vehicle records) and systems (like legacy systems for vehicle history).</li><li><strong>WunderGraph</strong> provides a unified API layer (REST and GraphQL) that aggregates data from DreamFactory and other services like third-party insurance verification systems.</li><li>Each <strong>channel</strong> (mobile app, web portal, kiosk) interacts with the <strong>same APIs</strong> exposed by WunderGraph, which means:</li><li>The mobile app and web portal get data from the <strong>same backend</strong> through standardised GraphQL queries.</li><li>The kiosks use <strong>REST APIs</strong> generated by WunderGraph from the same data layer.</li><li>Call centers access the same APIs to provide consistent information to citizens over the phone.</li></ul><h4>Business Value</h4><p>This ensures that the <strong>Vehicle Registration Service</strong> delivers a <strong>consistent experience</strong> across all touchpoints. Whether a user accesses the service via their mobile phone or interacts with a call center agent, they see the same vehicle data and can perform the same registration tasks seamlessly.</p><h3>API Modernisation</h3><p><strong>API modernisation</strong> involves transforming legacy systems and exposing them through modern API protocols (REST/GraphQL), making it easier to integrate with new systems, services, and channels. This enhances scalability, performance, and interoperability.</p><h4>Example: Modernising Legacy Driver’s License Management System</h4><p>Let us assume that RTA has a <strong>legacy driver’s license management system</strong> (e.g., a SOAP-based service or a custom-built monolithic system running on outdated hardware).</p><h4>How the Unified API Layer Modernises the System:</h4><ul><li><strong>DreamFactory</strong> can take the legacy database or SOAP service and <strong>automatically generate REST APIs</strong> to expose the driver’s license data and services (such as applying for a license, checking renewal status).</li><li><strong>WunderGraph</strong> takes these REST APIs from DreamFactory and <strong>exposes them as GraphQL APIs</strong>, making them more modern, flexible, and efficient.</li><li>Frontend applications (such as a new web-based Driver’s License Portal) use <strong>Unified</strong> <strong>GraphQL API</strong> to request only the data they need (e.g., license number, expiry date), improving performance compared to calling entire REST API endpoints.</li><li>If your frontend can only work with <strong>REST APIs</strong>, WunderGraph allows you to expose <strong>REST endpoints</strong> that internally translate the requests into <strong>GraphQL queries</strong> to the Unified API Layer.</li><li><strong>How it works</strong>: WunderGraph can expose a RESTful endpoint, for example:</li></ul><pre>POST /api/drivers/licenses/12345</pre><p>This REST request will be translated by WunderGraph into a GraphQL query behind the scenes. WunderGraph will then execute the GraphQL query against the Unified API Layer, gather the data, and return it in a REST-compliant format to the frontend.</p><ul><li><strong>Example</strong>: A frontend system sends a <strong>REST request</strong> to a WunderGraph-generated endpoint:</li></ul><p>GET /api/drivers/licenses/12345</p><p>WunderGraph transforms this request into a GraphQL query internally:</p><pre># GraphQL code<br>query {<br>  getDriverLicense(id: &quot;12345&quot;) {<br>    name<br>    expiryDate<br>    licenseStatus<br>  }<br>}</pre><p>It fetches the necessary data, then formats it into a <strong>JSON response</strong> typical of REST APIs and sends it back to the frontend.</p><p><strong>Benefit</strong>: This allows legacy frontends or systems restricted to REST to still consume the modern GraphQL-powered backend without needing significant changes to the frontend code.</p><p>WunderGraph can also <strong>cache</strong> commonly accessed data (such as license verification requests) for improved performance, reducing load on legacy systems.</p><h4>Business Value:</h4><p>This modernisation allows Organisations to expose their legacy driver’s license system via <strong>modern APIs</strong> that are easy to consume by new web portals, mobile apps, and third-party integrators (e.g., insurance companies checking driver records). The system becomes scalable, performant, and much easier to integrate into future applications.</p><p>● <strong>Omnichannel Experience</strong>: The unified API layer ensures that all citizen-facing platforms (mobile, web, kiosks) can interact with the same services and data in real time, providing a seamless and consistent experience across all channels.</p><p>●<strong> API Modernisation</strong>: By leveraging DreamFactory to generate APIs from legacy systems and WunderGraph to expose them as modern, flexible APIs (GraphQL or REST), Organisations can modernise legacy systems without rebuilding them, making them scalable and accessible for future digital transformations.</p><h3>Conclusion</h3><p>These two Open-Source Low-Code Platforms working together streamline integration, improve user experience, and prepare Organisations for transitioning into future technological advancements, ensuring the infrastructure is both <strong>modern and omnichannel-ready</strong>.</p><p>By embracing this synergy, businesses not only reduce complexity and operational costs but also foster innovation through faster deployment cycles, stronger interoperability, and resilient architectures. Ultimately, this collaboration empowers organisations to remain agile, competitive, and equipped to continuously adapt in an evolving digital landscape.</p><h3>What’s Next</h3><p>This is a two part blog, where in this <a href="https://medium.com/@shubhojit.dasgupta/enhanced-omnichannel-experience-with-unified-api-layer-1cabff44e895"><strong>part</strong></a> we covered the following;</p><p>● <strong>Unified API Layer:</strong> This blog introduces a robust, fully-integrated Unified API Layer that acts as an abstraction between multiple APIs, omni-channel systems, modern/legacy systems, databases, and applications. This layer provides a single point of access and a standardised interface for different services, simplifying how developers interact with multiple APIs.</p><p>● <strong>Proposed Platform &amp; Architecture:</strong> We proposed the platform and High-Level Architecture combining strengths of DreamFactory &amp; WunderGraph, leveraging low-code open-source platforms for seamless API generation, orchestration &amp; integration with minimal code. This enables efficient API creation from multiple data sources and advanced API orchestration for Microservices, legacy systems, databases, IoT devices, and external RESTful APIs.</p><p>● <strong>DreamFactory:</strong> DreamFactory is highlighted as an open-source REST API generation solution that automatically generates secure and documented APIs for various databases. It includes features like user management, token-based authentication, role-based access control, OAuth 2.0, OpenID Connect, and API keys with basic rate limiting.</p><p>● <strong>WunderGraph:</strong> WunderGraph is described as a Backend for Frontend (BFF) framework designed to optimise developer workflows through API composition. It combines API Gateway and Backends for Frontends patterns, providing single-purpose edge services for UIs and external parties. WunderGraph enables developers to compose and unify multiple APIs into a single unified GraphQL API Schema.</p><p>● <strong>Working Together:</strong> The Blog explains how DreamFactory &amp; WunderGraph work together. DreamFactory generates and exposes APIs from various backends/Databases, while WunderGraph orchestrates and integrates these APIs into a single GraphQL endpoint. This combination provides a unified API layer, offering access to all underlying APIs exposed by DreamFactory or other services.</p><p>● <strong>Decoupled and Extendible Architecture:</strong> The Blog describes how the Unified API &amp; Orchestration Layer (built using WunderGraph) and the REST API Generation Layer (from DreamFactory) are decoupled to ensure clear boundaries in terms of responsibility, communication, and management. This separation allows for independent deployment, version control, and flexible integration of additional systems without impacting the core logic of either layer. The architecture is designed to be scalable, maintainable, and adaptable to changes in either layer.</p><p>● <strong>Omnichannel Experience: </strong>The unified API layer supports an omnichannel experience by delivering a seamless, integrated service across multiple channels such as mobile apps, web platforms, kiosks, and call centres. This ensures consistency and accessibility, allowing all channels to interact with the same data and services.</p><p>● <strong>API Modernisation: </strong>Discussed API modernisation, which involves transforming legacy systems and exposing them through modern API protocols (REST/GraphQL). This enhances scalability, performance, and interoperability, making it easier to integrate with new systems, services, and channels.</p><p>In the <a href="https://medium.com/@shubhojit.dasgupta/ai-driven-unified-api-layer-d6d14a6da5d4"><strong>next part</strong></a> of the Blog ,we shall explore how to leverage the Modern Unified API experience with AI/ML integrations and pipeline. We shall also cover at a high-level the overall Infrastructure &amp; Networking Architecture along with a Robust and Integrated Observability Stack. The <a href="https://medium.com/@shubhojit.dasgupta/ai-driven-unified-api-layer-d6d14a6da5d4"><strong>next part</strong></a> of the Blog, also covers, API led AI experiences with the Kong AI Gateway.</p><p>Let’s dive into the <a href="https://medium.com/@shubhojit.dasgupta/ai-driven-unified-api-layer-d6d14a6da5d4"><strong>second part</strong></a> of the Blog: <a href="https://medium.com/@shubhojit.dasgupta/ai-driven-unified-api-layer-d6d14a6da5d4"><strong>AI Driven Unified API Layer</strong></a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1cabff44e895" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Managing APIs in Kubernetes with Kong Ingress Controller]]></title>
            <description><![CDATA[<div class="medium-feed-item"><p class="medium-feed-image"><a href="https://medium.com/@shubhojit.dasgupta/managing-apis-in-kubernetes-with-kong-ingress-controller-2a3cba85a1e3?source=rss-88db77259f8a------2"><img src="https://cdn-images-1.medium.com/max/850/1*uiOFIIUfFa7M29bRlpgYwQ.png" width="850"></a></p><p class="medium-feed-snippet">Shubhojit Dasgupta&#x200A;&#x2014;&#x200A;Independent API Architect</p><p class="medium-feed-link"><a href="https://medium.com/@shubhojit.dasgupta/managing-apis-in-kubernetes-with-kong-ingress-controller-2a3cba85a1e3?source=rss-88db77259f8a------2">Continue reading on Medium »</a></p></div>]]></description>
            <link>https://medium.com/@shubhojit.dasgupta/managing-apis-in-kubernetes-with-kong-ingress-controller-2a3cba85a1e3?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/2a3cba85a1e3</guid>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[kubernetes-service]]></category>
            <category><![CDATA[kong-ingress-controller]]></category>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[kubernetes-ingress]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Mon, 29 Sep 2025 10:41:36 GMT</pubDate>
            <atom:updated>2025-09-29T10:42:54.754Z</atom:updated>
        </item>
        <item>
            <title><![CDATA[Dynamic Routing & Transformations Part 16]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/33893b1453c9</guid>
            <category><![CDATA[kong-api-gateway]]></category>
            <category><![CDATA[keycloak]]></category>
            <category><![CDATA[kong-konnect]]></category>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[insomnia]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Sun, 21 Sep 2025 17:27:07 GMT</pubDate>
            <atom:updated>2025-09-21T17:28:09.456Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Shubhojit Dasgupta — API Architect, HUCO FZCO (Dubai)</strong></p><h3>Testing Dynamic Routing &amp; Transformation from the Browser</h3><h4>Testing Banking Service API For Savings Account Customer</h4><figure><img alt="Saving Customer Authorisation By Keycloak." src="https://cdn-images-1.medium.com/max/883/1*05vz1elIPwHpz_n9P-vn8w.png" /><figcaption>Figure 1: Authorising Savings Customer to access banking service from the browser</figcaption></figure><figure><img alt="API Request from Savings Customer to access banking App." src="https://cdn-images-1.medium.com/max/582/1*0QSPOqAQWNNb9IybJTkLgw.png" /><figcaption>Figure 2: API Request from Savings Customer to access banking App</figcaption></figure><p>The <em>savings account</em> user is redirected to the <em>/savings-account</em> <em>route</em> path in the <em>banking</em> service.</p><h4>Testing Banking Service API For Current Account Customer</h4><figure><img alt="Authorising the Current Account User from Keycloak before accessing the Banking App." src="https://cdn-images-1.medium.com/max/855/1*wtEgJHMa_cEGDPQCeEzIcw.png" /><figcaption>Figure 3: Authorising the Current Account User from Keycloak before accessing the Banking App API</figcaption></figure><figure><img alt="API Request from the Current Account Customer to access the banking App." src="https://cdn-images-1.medium.com/max/565/1*p7kqHfN8Ysyf-OiHVN4sSg.png" /><figcaption>Figure 4: API Request from the Current Account Customer to access the banking App</figcaption></figure><p>The <em>current account</em> user is redirected to the <em>/current-account</em> <em>route</em> path in the <em>banking</em> service.</p><h3>Troubleshooting &amp; Debugging Common Issues</h3><p>In the <em>proxy_error.log</em> file, Kong generates and stores all the error details included in the <em>kong/shared/logs</em> host folder while running and executing API requests from clients. The path for <em>proxy port</em> request <em>error logs</em> is configured in the <em>KONG_PROXY_ERROR_LOG</em> <em>environment</em> variable of the <em>kong-dp</em> service definition. This path maps to the host application folder path specified in the <em>volumes</em> section of the <em>kong-dp</em> <em>service container</em> definition.</p><p>Not able to apply recent configuration changes to the Kong Gateway while testing the APIs. This happens when the Gateway is not in sync with the Konnect Control Plane. This can be observed from the following error message in the <em>proxy_error.log</em> log file generated from Kong.</p><pre>2024/07/15 14:29:56 [error] 2406#0: *8 [lua] data_plane.lua:385: communicate(): [clustering] did not receive pong frame from control plane within 45 seconds [d90c1bbe77.us.cp0.konghq.com:443], context: ngx.timer<br>2024/07/15 16:43:44 [error] 2406#0: *10311 [lua] data_plane.lua:385: communicate(): [clustering] did not receive pong frame from control plane within 45 seconds [d90c1bbe77.us.cp0.konghq.com:443], context: ngx.timer<br>2024/07/15 17:49:16 [error] 2406#0: *14966 [lua] data_plane.lua:385: communicate(): [clustering] did not receive pong frame from control plane within 45 seconds [d90c1bbe77.us.cp0.konghq.com:443], context: ngx.timer</pre><p>Wait until <em>Kong Data Plane node</em> is in sync with the <em>Konnect Control</em> Plane. This can be <em>verified</em> from the <em>Konnect UI</em>. Go to the <em>Gateway Manager</em> section from the left-side menu. Select the <em>Control Plane</em>. In the <em>Gateway Manager’s Control Plane </em>section, select the Data Plane Nodes section. You will be redirected to the <em>Data Plane Nodes</em> information page where one can see the <em>kong-dp Data Plane</em> <em>node</em> running with <em>Sync Status</em> as <em>In Sync and </em>Compatible.</p><figure><img alt="Kong Data Plane Nodes." src="https://cdn-images-1.medium.com/max/1024/1*M5g_GWH50g2hhApTXJLi5Q.png" /><figcaption>Figure 5: Kong Konnect Data Plane Nodes</figcaption></figure><p>Notice the “<em>Labels</em>” column in the <em>Data Plane Nodes</em> information page. It designates the <em>Kong Gateway runtime</em> running in the <em>Kong Konnect SaaS</em> Platform. It is the same label specified in the <em>KONG_CLUSTER_DP_LABELS</em> configuration parameter of the <em>kong-dp</em> service container definition and interpolated by the <em>KONG_DP_LABLES</em> environment key as imported from the “<em>.env</em>” file in the “<em>docker-compose.yaml</em>” <em>Docker Compose</em> specification file.</p><p>For any compatible issues or errors in the Kong Gateway click on the host <em>kong-dp</em> to review the configuration details and error message in the “<em>Data Plane Node Details</em>” page from the UI.</p><figure><img alt="The kong-dp Data Plane Node Details." src="https://cdn-images-1.medium.com/max/1024/1*ggB9unxnunO-e5UwOlaTIQ.png" /><figcaption>Figure 6: Konnect Data Plane Node Details</figcaption></figure><p>The Kong Gateway runtime has no compatible issues as seen from the info displayed at the top of the <em>Konnect UI</em> and from the compatibility status in the “<em>Data Plane Node Details</em>” Page.</p><p>The “<em>Errors</em>” list is empty indicating there are no errors in the <em>Kong Gateway</em> configuration. API requests via <em>Kong Gateway</em> can be tested to verify that all features are working based on the latest configuration applied using <em>decK</em> or <em>Konnect API</em> into the <em>Kong Gateway Data Plane</em> node.</p><p>If you are trying to access the <em>Kong proxy gateway </em>or <em>Keycloak server</em> hosted locally from a secured URL using the HTTPS protocol, you may run into issues with SSL certificate verification. This problem occurs when the self-signed localhost certificate expires after a month.</p><p>To resolve this issue in Kong, you will need to generate a new SSL server certificate and key. Then, update the configuration parameters in the “<em>docker-compose.yaml</em>” file for the <em>kong-dp</em> service container definition. Add the path of the certificate key to the <em>KONG_SSL_CERT_KEY</em> configuration parameter and the server certificate path to the <em>KONG_SSL_CERT</em> configuration parameter. For the <em>keycloak service </em>container definition, add the path of localhost server certificate to <em>KC_HTTPS_CERTIFICATE_FILE</em> configuration parameter and the certificate key path to the environment variable <em>KC_HTTPS_CERTIFICATE_KEY_FILE</em> configuration parameter.</p><p>When making configuration changes such as onboarding new APIs and security plugins using <em>decK</em> commands or Konnect API requests, you may encounter 401 unauthorised responses. This occurs if the <em>Konnect Personal Access Token</em> has expired. To resolve this, generate a new <em>Personal Access Token</em>, securely store it in the “<em>novigo_accelerators.deck.yaml</em>” file, and include it with every <em>decK</em> <em>command</em> or <em>Kong API</em> request. This will authorise the applied changes and fix the issue.</p><h3>Conclusion</h3><p>In <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9"><strong>part-16</strong></a><strong> </strong>of this Blog , we covered the following;</p><p>• Testing the <em>Banking service</em> API for <em>Savings &amp; Current customer </em>from the <em>browser</em>, redirecting the user to <em>/savings-account</em> and <em>/current-account</em> <em>route</em> paths in the <em>banking</em> service, respectively and dynamically via the Kong Gateway.</p><p>• Testing that the transformations are applied correctly via the Kong Gateway from the browser for <em>Savings &amp; Current customer </em>respectively.</p><p>• Troubleshooting and debugging common issues within Kong Gateway.</p><p>• Validating <em>Kong Data Plane</em> nodes compatibility and errors in the Gateway from the Konnect UI.</p><p>Blogs from <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-1-655a2261ce06"><strong>part-1</strong></a> to <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9"><strong>part-16</strong></a> covers dynamic routing via <em>JWT token claim</em> parameters to determine route paths at runtime, with <em>url</em> transformations. It explains exhaustively how to utilise the claim parameters in the JWT token to dynamically direct the incoming requests to the appropriate route paths based on specific user or client attributes. Additionally, it covers the process of applying transformations to the incoming data based on the JWT token claim parameters, allowing for personalized responses tailored to the user’s attributes or access rights. Overall, it provides an in-depth guide on leveraging JWT token claim parameters for dynamic routing and transformations, enhancing the flexibility and customisation of the application’s routing and data processing.</p><p>Visit <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295"><strong>part-15</strong></a> of the Blog, where the Banking service API was tested for both <em>Savings</em> and <em>Current</em> <em>customers</em> using the <em>Insomnia client</em> in combination with <em>Kong Gateway</em>. <em>Request chaining</em> and <em>pre-request scripts</em> were implemented to test if <em>Savings</em> and <em>Current</em> <em>customer </em>users are dynamically redirected to the /savings-account and /current-account routes. In <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295"><strong>part-15</strong></a> of the Blog, we also explored <em>JavaScript-based pre-request scripts</em> in <em>Insomnia</em> to update <em>environment variables</em>, manage <em>bearer tokens</em>, and set <em>authorisation</em> header before sending API requests. For <em>Savings customers</em>, tokens were generated and applied to set an environment variable in authorisation header, while for <em>Current customers</em> the Auth header was updated either directly with a valid JWT or by generating a new token when required, validated first through Keycloak’s introspection endpoint. In all scenarios, valid tokens were appended to authorisation headers to securely access the Banking service API through Kong Gateway.</p><p>The entire implementation depicted in these blogs, shows how one can securely onboard a Banking API service via decK &amp; bash scripts, ensuring that the API is managed via Kong Gateway securely and reliably. It covers associated technologies like Docker Compose, Python Application Development &amp; Containerisation, and Keycloak IdP, right from installation and setting up security measures to testing and review using API design and testing tool like Insomnia with the latest features built by Kong.</p><h3>Summary of Dynamic Routing &amp; Transformations via Kong Gateway managed by Kong Konnect Platform</h3><figure><img alt="Summarising Dynamic Routing &amp; Transformation." src="https://cdn-images-1.medium.com/max/1024/1*2XTm3p5NgmpHaHMQwtdMUA.png" /><figcaption>Figure 7: Summarising Dynamic Routing and Transformations via Kong gateway connected to the Kong Konnect</figcaption></figure><p>One can see how easy it is to leverage <em>Kong API Gateway</em> to create complex <em>dynamic routing</em> based on specific authentication attributes (in our case, JWT token claims).</p><p>All users have the same <em>Login</em> process, and according to their <em>JWT claim attributes </em>these <em>customers</em> are <em>dynamically</em> <em>routed</em> to the relevant <em>application/path</em> for one’s <em>banking application </em>service. This makes the maintenance of the deployed application much easier and cleaner.</p><p>In this solution, we used <em>Kong’s Konnect (SaaS) platform</em> which makes <em>deployment</em> and <em>maintenance</em> much easier. We can deploy Kong in many architectures (on-prem, cloud, hybrid, docker, k8s, etc…), and can reproduce these capabilities across environments no matter which form of deployment you choose.</p><p>By leveraging <em>dynamic routing</em>, developers can focus on building and iterating on their APIs while their <em>API platform infrastructure</em> takes care of routing requests efficiently and reliably.</p><p>Customers now expect outstanding experiences — and these experiences require more from applications and developers. For this, an API gateway like Kong is a crucial component. The right API management solution can make the difference between an experience that drives revenue and one that drives customers to the competition.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=33893b1453c9" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dynamic Routing & Transformations Part 15]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/d9b519b3a295</guid>
            <category><![CDATA[kong-konnect]]></category>
            <category><![CDATA[dynamic-routing-gateway]]></category>
            <category><![CDATA[kong-gateway]]></category>
            <category><![CDATA[pre-request-script]]></category>
            <category><![CDATA[kong-api-gateway]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Sun, 21 Sep 2025 11:10:25 GMT</pubDate>
            <atom:updated>2025-09-21T17:29:43.651Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Shubhojit Dasgupta — API Architect, HUCO FZCO (Dubai)</strong></p><h3>Banking Service API Testing Using Insomnia</h3><p>The Banking service requested via the Kong Gateway through Insomnia requires tokens that can be generated automatically with request chaining or the pre-request script using Insomnia.</p><h3>Savings Customer API Call Using Request Chaining</h3><p>Get the token from the <em>Keycloak Token API</em> response for the <em>saving customer</em> before sending the request to the Banking service from Insomnia. In the <em>Auth</em> section of <em>Insomnia</em> select Bearer Token as the authorisation type. In the <em>Token</em> section click on the Response label.</p><figure><img alt="Banking API Call from Savings Customer With Request Chaining." src="https://cdn-images-1.medium.com/max/1024/1*YsrnlbeA80-IujP9XxXYqA.png" /><figcaption>Figure 1: Savings Customer Sends an API Request with request chaining to access Banking Service</figcaption></figure><figure><img alt="Edit the Authorisation token attribute in the API request from the savings customer to access the Banking Service." src="https://cdn-images-1.medium.com/max/1024/1*wJw1VI-hNyHZKh5Yajv1eA.png" /><figcaption>Figure 2: Request Chaining By Using The Token Generation API for Savings Customer</figcaption></figure><p>In the Request dropdown select the <em>Keycloak Token API</em> for <em>Savings</em> <em>Account</em> User. Select the “<em>When Expired</em>” option from the <em>Trigger Behavior</em> dropdown list so that a request to generate the token is only made when the existing token has expired. Filter the response by entering <em>$.access_token</em>. The value will be dependent on the token API response. If you have set it up correctly, you should see a token in <strong>Live Preview</strong>.</p><figure><img alt="API Request from Saving Customer." src="https://cdn-images-1.medium.com/max/1024/1*rSlrrpaXkjWpUD998OAF6A.png" /><figcaption>Figure 3: Sending an API request from Savings Customer By Request Chaining</figcaption></figure><p>The <em>savings account</em> user’s API request redirects the user to the <em>/savings-account</em> route path in the banking service application through the <em>Kong API Gateway</em> based on the token claim.</p><h3>Savings Customer API Call Using Pre-Request Script</h3><p>The <em>pre-request</em> script updates the <em>saving_account_access_token</em> environment variable with a valid token. It verifies the existing token value assigned to the <em>saving_account_access_token</em> environment variable and if the <em>access token</em> is valid it uses the token to authorise the user.</p><p>The <em>pre-request</em> script uses the <em>introspection API</em> endpoint in Keycloak to validate the token. If the response declares the token as <em>inactive</em> then generate a fresh token and assign this token to <em>saving_account_access_token</em> environment variable.</p><pre>// Keycloak token generation endpoint and client credentials<br>const tokenUrl = insomnia.environment.get(&quot;token_url&quot;);<br>const clientId = insomnia.environment.get(&quot;client_id&quot;);<br>const clientSecret = insomnia.environment.get(&quot;client_secret&quot;);<br>const scope = insomnia.environment.get(&quot;scope&quot;);<br>const username = insomnia.environment.get(&quot;saving_account_username&quot;);<br>const password = insomnia.environment.get(&quot;saving_account_password&quot;);<br>const grantType = insomnia.environment.get(&quot;grant_type&quot;);<br><br>// Keycloak introspection endpoint<br>const introspectionUrl = insomnia.environment.get(&quot;introspection_url&quot;);<br><br>// Active request authorization token<br>const accessToken = insomnia.environment.get(&quot;saving_account_access_token&quot;);<br><br>/*Payload for introspection endpoint in Keycloak IdP<br>with urlencoded content in the body of the request*/<br>const verifyTokenReq = {<br>  method: &#39;POST&#39;,<br>  url: introspectionUrl,<br>  header: {<br>    &#39;Content-Type&#39;: &#39;application/x-www-form-urlencoded&#39;,<br>  },<br>  body: {<br>    mode: &#39;urlencoded&#39;,<br>    urlencoded: [<br>      { key: &#39;token&#39;, value: accessToken, },<br>      { key: &#39;client_id&#39;, value: clientId, },<br>      { key: &#39;client_secret&#39;, value: clientSecret, },<br>    ]<br>  }<br>};<br><br>/*Send a request to Keycloak IdP introspection endpoint<br>to verify if an access token in active request is valid*/<br>const introspectionResp = await new Promise((resolve, reject) =&gt; {<br>  insomnia.sendRequest(<br>    verifyTokenReq,<br>    (err, resp) =&gt; err != null ? reject(err) : resolve(resp)<br>  );<br>});<br><br>/*Verify the validity of access token on successful response <br>from Keycloak IdP introspection endpoint request for a client*/<br>if (introspectionResp.code == 200 &amp;&amp; introspectionResp.json().active) {<br>  // JSON response<br>  let jsonResp = introspectionResp.json();<br>  console.log(&quot;Access token active: &quot; + jsonResp.active);<br>  <br>} // Generate new token for client authorization when the token in active request is invalid<br>else {<br>  console.log(&quot;Access token is invalid:&quot;, introspectionResp.json());<br>  <br>  /*Payload for sending a new token generation request with <br>  urlencoded content to Keycloak token generation endpoint*/<br>  const getTokenReq = {<br>    method: &#39;POST&#39;,<br>    url: tokenUrl,<br>    header: {<br>      &#39;Content-Type&#39;: &#39;application/x-www-form-urlencoded&#39;,<br>    },<br>    body: {<br>      mode: &#39;urlencoded&#39;,<br>      urlencoded: [<br>        { key: &#39;client_id&#39;, value: clientId, },<br>        { key: &#39;client_secret&#39;, value: clientSecret, },<br>        { key: &#39;scope&#39;, value: scope, },<br>        { key: &#39;username&#39;, value: username, },<br>        { key: &#39;password&#39;, value: password, },<br>        { key: &#39;grant_type&#39;, value: grantType, },<br>      ]<br>    }<br>  };<br>  <br>  console.log(&quot;Generating new access token&quot;);<br>  <br>  /*Sending a request to Keycloak IdP token generation endpoint<br>  and generating a new access token for authorizing the client*/<br>  const resp = await new Promise((resolve, reject) =&gt; {<br>    insomnia.sendRequest(<br>      getTokenReq,<br>      (err, resp) =&gt; err != null ? reject(err) : resolve(resp)<br>    );<br>  });<br>  <br>  /*On successfully generating the token automatically from Keycloak <br>  update the active request authorization type with new access token*/<br>  if (resp.code == 200) {<br>    // JSON response<br>    const jsonResp = resp.json();<br>    <br>    // New access token from Keycloak&#39;s token generation endpoint response<br>    const newAccessToken = jsonResp.access_token;<br>    console.log(&quot;New access token: &quot; + newAccessToken);<br>    <br>    // Set access token variable with the new access token<br>    insomnia.environment.set(&quot;saving_account_access_token&quot;, newAccessToken);<br>    console.log(&quot;Access token variable updated in &quot; + insomnia.environment._name + &quot; environment&quot;);<br>  } else {<br>    // On failure to fetch a new access token from Keycloak&#39;s token generation endpoint<br>    console.error(&quot;Unable to fetch token, response status: &quot; + resp.code);<br>  }<br>}</pre><figure><img alt="Pre-Request Script to Generate User token to Test the Banking Service API request." src="https://cdn-images-1.medium.com/max/1024/1*upm_rGE5nuFABDk6uqdtaQ.png" /><figcaption>Figure 4: Pre-Request Script Executes to Generate a valid Token Before Sending an API request to the Banking Service</figcaption></figure><h3>Current Account User API Call Using Pre-Request Script</h3><p>The <em>Pre-Request</em> script for the current account user to access the banking service does not use any environment variable for storing the authorisation token. The script directly updates the active API request authorisation type and token and adds it as the authorisation header for the active request before sending the API call to the banking service.</p><pre>// Keycloak token generation endpoint and client credentials<br>const tokenUrl = insomnia.environment.get(&quot;token_url&quot;);<br>const clientId = insomnia.environment.get(&quot;client_id&quot;);<br>const clientSecret = insomnia.environment.get(&quot;client_secret&quot;);<br>const scope = insomnia.environment.get(&quot;scope&quot;);<br>const username = insomnia.environment.get(&quot;current_account_username&quot;);<br>const password = insomnia.environment.get(&quot;current_account_password&quot;);<br>const grantType = insomnia.environment.get(&quot;grant_type&quot;);<br><br>// Keycloak introspection endpoint<br>const introspectionUrl = insomnia.environment.get(&quot;introspection_url&quot;);<br><br>// Active request authorization token<br>const accessToken = insomnia.environment.get(&quot;current_account_access_token&quot;);<br><br>/*Payload for introspection endpoint in Keycloak IdP<br>with urlencoded content in body of the request*/<br>const verifyTokenReq = {<br>  method: &#39;POST&#39;,<br>  url: introspectionUrl,<br>  header: {<br>    &#39;Content-Type&#39;: &#39;application/x-www-form-urlencoded&#39;,<br>  },<br>  body: {<br>    mode: &#39;urlencoded&#39;,<br>    urlencoded: [<br>      { key: &#39;token&#39;, value: accessToken, },<br>      { key: &#39;client_id&#39;, value: clientId, },<br>      { key: &#39;client_secret&#39;, value: clientSecret, },<br>    ]<br>  }<br>};<br><br>/*Send a request to Keycloak IdP introspection endpoint to <br>verify if existing access token for the active request is valid*/<br>const introspectionResp = await new Promise((resolve, reject) =&gt; {<br>  insomnia.sendRequest(<br>    verifyTokenReq,<br>    (err, resp) =&gt; err != null ? reject(err) : resolve(resp)<br>  );<br>});<br><br>/*Function to update active request authorization type<br><br>type(string): Authorization type<br>token(string): Authorization token<br>*/<br>let updateAuthActiveReq = (type, token) =&gt; {<br>    /*Set the auth type in active request with <br>    an access token generated automatically*/<br>    insomnia.request.auth.update({<br>      type: type,<br>      bearer: [<br>        { key: &#39;token&#39;, value: token, },<br>      ],<br>    }, type);<br>    console.log(&quot;Auth token updated in the active request&quot;);<br>};<br><br>/*Verify the validity of access token on successful response <br>from Keycloak IdP introspection endpoint request for a client*/<br>if (introspectionResp.code == 200 &amp;&amp; introspectionResp.json().active) {<br>  // JSON response<br>  let jsonResp = introspectionResp.json();<br>  console.log(&quot;Access token active:&quot;, jsonResp.active);<br>  <br>  // Update active request bearer auth with the existing access token variable<br>  updateAuthActiveReq(&#39;bearer&#39;, accessToken);<br>  <br>} // Generate new token for client authorization when the token in active request is invalid<br>else {<br>  console.log(&quot;Access token is invalid:&quot;, introspectionResp.json());<br>  <br>  /*Payload for sending a new token generation request with <br>  urlencoded content to Keycloak token generation endpoint*/<br>  const getTokenReq = {<br>    method: &#39;POST&#39;,<br>    url: tokenUrl,<br>    header: {<br>      &#39;Content-Type&#39;: &#39;application/x-www-form-urlencoded&#39;,<br>    },<br>    body: {<br>      mode: &#39;urlencoded&#39;,<br>      urlencoded: [<br>        { key: &#39;client_id&#39;, value: clientId, },<br>        { key: &#39;client_secret&#39;, value: clientSecret, },<br>        { key: &#39;scope&#39;, value: scope, },<br>        { key: &#39;username&#39;, value: username, },<br>        { key: &#39;password&#39;, value: password, },<br>        { key: &#39;grant_type&#39;, value: grantType, },<br>      ]<br>    }<br>  };<br>  <br>  console.log(&quot;Generating new access token&quot;);<br>  <br>  /*Sending a request to Keycloak IdP token generation endpoint<br>  and generating a new access token for authorizing the client*/<br>  const resp = await new Promise((resolve, reject) =&gt; {<br>    insomnia.sendRequest(<br>      getTokenReq,<br>      (err, resp) =&gt; err != null ? reject(err) : resolve(resp)<br>    );<br>  });<br>  <br>  /*On successfully generating the token automatically from Keycloak <br>  update the active request authorization type with the new access token*/<br>  if (resp.code == 200) {<br>    // JSON response<br>    const jsonResp = resp.json();<br>    <br>    // New access token from Keycloak&#39;s token generation endpoint response<br>    const newAccessToken = jsonResp.access_token;<br>    console.log(&quot;New access token: &quot; + newAccessToken);<br>    <br>    // Update active request bearer auth with the new access token<br>    updateAuthActiveReq(&#39;bearer&#39;, newAccessToken);<br>    <br>    // Set access token variable with the new access token<br>    insomnia.environment.set(&quot;current_account_access_token&quot;, newAccessToken);<br>    console.log(&quot;Access token variable updated in &quot; + insomnia.environment._name + &quot; environment&quot;);<br><br>  } else {<br>    // On failure to fetch a new access token from Keycloak&#39;s token generation endpoint<br>    console.error(&quot;Unable to fetch token, response status: &quot; + resp.code);<br>  }<br>}</pre><p>If the token in the active request is invalid the pre-request script generates a new token and updates the active request bearer auth with the new token. The valid token is added to the authorisation header to test the API call for the current account customer through Insomnia.</p><figure><img alt="API request from the current customer to access banking service with pre-request script running before sending the request." src="https://cdn-images-1.medium.com/max/1024/1*BW7w6AauHK9stKGWLR5jFg.png" /><figcaption>Figure 5: Pre-Request Script adds the auth header before the current account customer accesses the banking service.</figcaption></figure><p>API request from the <em>current account</em> user redirects the user to the <em>/current-account</em> route path in the <em>banking service</em> application through the Kong API Gateway based on the token claim.</p><h3>What’s Next</h3><p>In <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295"><strong>part-15</strong></a><strong> </strong>of this Blog , we covered the following;</p><p>• Testing the <em>Banking service</em> API as a <em>Savings customer </em>from <em>Insomnia</em> Client using <em>request chaining</em> feature and redirecting the user to <em>/savings-account</em> route path via the Kong Gateway.</p><p>• Testing the <em>Banking service</em> API as a <em>Savings customer </em>from <em>Insomnia</em> Client using <em>pre-request scripts </em>and redirecting the user to <em>/savings-account</em> route path via the Kong Gateway.</p><p>• Hands-on scripting in <em>JavaScript</em> using <em>Insomnia’s</em> <em>pre-request </em>script feature.</p><p>• Redirecting the <em>Savings customer</em> to <em>/savings-account</em> route path <em>Dynamically</em> via the <em>Kong</em> Gateway using <em>Insomnia</em> Client and authorising/authenticating the user by updating <em>environment</em> <em>variable</em> for <em>bearer token</em> in <em>Auth</em> header via the <em>pre-request </em>script executed in <em>Insomnia</em> before sending the API request to the <em>Banking service</em> API via the <em>Kong</em> Gateway.</p><p>• Testing the <em>Banking service</em> API as a <em>Current</em> <em>customer </em>from <em>Insomnia</em> Client using <em>pre-request </em>script feature and redirecting the user <em>Dynamically </em>to the <em>/current-account</em> route path in the <em>banking service</em> API via the <em>Kong</em> Gateway.</p><p>• Updating the Auth header of the <em>Banking</em> API request while testing for the <em>Current</em> <em>customer </em>directly, without using any environment variable, with a valid JWT token, while running the <em>pre-request </em>script in Insomnia, before sending the request to the <em>Banking</em> <em>service</em> API via the <em>Kong</em> Gateway.</p><p>• Checking the validity of the token using the <em>introspection API</em> endpoint in Keycloak, before the <em>pre-request</em> script in Insomnia generates a new token, if token is invalid.</p><p>• Adding a valid token as <em>authorisation</em> header to test the <em>Banking service</em> API call for the <em>current</em> account customer through <em>Insomnia</em> via Kong Gateway.</p><p>Visit <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-14-e0c5782a685c"><strong>part-14</strong></a> of the Blog, to test the <em>token generation</em> API of <em>Keycloak</em> using <em>Insomnia</em> client tool. Here, we configure Kong Insomnia with environment variables for the request body and authentication details, to send API calls to the <em>token</em> generation endpoint of <em>Keycloak</em>, then verify the token API for both <em>saving</em> and <em>current</em> account customers. We then test the token API by sending <em>POST</em> requests to generate tokens for banking customers.</p><p>Next, in <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9"><strong>part-16</strong></a> of the Blog we will test the <em>Banking service</em> API calls for <em>Savings </em>and<em> Current</em> <em>customers </em>via browser to <em>validate Dynamic routing &amp; transformations</em> . In <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9"><strong>part-16</strong></a> of the Blog we will <em>troubleshoot</em> <em>banking service</em> API requests via Kong Gateway, debug common issues by inspecting <em>Kong proxy error logs </em>and the <em>Kong Konnect</em> UI for any errors, also we debug issues with SSL certificate verification while accessing the <em>Kong</em> proxy gateway or <em>Keycloak</em> server locally. Finally, we conclude the Blog in <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9"><strong>part-16</strong></a>.</p><p>Let’s dive into <strong>Part-16</strong> of the Blog: <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9">https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-16-33893b1453c9</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d9b519b3a295" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Dynamic Routing & Transformations Part 14]]></title>
            <link>https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-14-e0c5782a685c?source=rss-88db77259f8a------2</link>
            <guid isPermaLink="false">https://medium.com/p/e0c5782a685c</guid>
            <category><![CDATA[keycloak-integration]]></category>
            <category><![CDATA[insomnia]]></category>
            <category><![CDATA[kong-konnect]]></category>
            <category><![CDATA[jwt-token-generation]]></category>
            <category><![CDATA[kong-api-gateway]]></category>
            <dc:creator><![CDATA[Shubhojit Dasgupta]]></dc:creator>
            <pubDate>Mon, 15 Sep 2025 14:13:56 GMT</pubDate>
            <atom:updated>2025-09-21T11:12:30.838Z</atom:updated>
            <content:encoded><![CDATA[<p><strong>Shubhojit Dasgupta — API Architect, HUCO FZCO (Dubai)</strong></p><h3>Keycloak Token API Testing Using Insomnia</h3><p>The Keycloak server accepts <em>data</em> in <em>Form URL Encoded</em> format. API request to generate the <em>token</em> sends the <em>payload data</em> with <em>Content-Type</em> set to <em>application/x-www-form-urlencoded</em>. The Keycloak server accepts data sent as <em>form-encoded</em> parameters in the <em>body</em> of the API request and responds with token info in <em>JSON</em> format.</p><figure><img alt="Keycloak token API request Body for Savings Customer." src="https://cdn-images-1.medium.com/max/1024/1*IKY5UlznzZDesHfLwrXqdQ.png" /><figcaption>Figure 1: Keycloak Token API Request Body for Savings Customer</figcaption></figure><p>The <em>scope</em> parameters, <em>openid</em> and <em>bank</em> are sent as part of the <em>form-encoded</em> parameters in the <em>body</em> of the API request, separated by whitespace. The authorisation type for the API request is specified as <em>Basic</em> in the <em>Auth</em> tab section of <em>Insomnia</em>. The <em>Username</em> is set to <em>client_id</em> and the <em>Password</em> is set to <em>client_secret</em>, as configured for the <em>kong</em> client in Keycloak <em>Kong</em> Realm.</p><figure><img alt="Keycloak Token API Authorisation for Savings Customer." src="https://cdn-images-1.medium.com/max/1024/1*i0k2Wwe_dhrB0F2yfhhBaQ.png" /><figcaption>Figure 2: Keycloak Token API Authorisation for Savings Customer</figcaption></figure><p>The <em>token API</em> request is a <em>POST </em>request to generate <em>tokens</em> for <em>Banking</em> Customers.</p><figure><img alt="Keycloak Token API Response for Savings Customer." src="https://cdn-images-1.medium.com/max/1024/1*d3Xa-GD6REr3xozYwwZlBQ.png" /><figcaption>Figure 3: Keycloak Token API Response for Savings Customer</figcaption></figure><figure><img alt="Keycloak Token API Response for Current Account Customer." src="https://cdn-images-1.medium.com/max/1024/1*3jlw1Sfomv0QZTN3I_cOXw.png" /><figcaption>Figure 4: Keycloak Token API Response for Current Account Customer</figcaption></figure><p>The Token generation endpoint responds with a <em>200 OK </em>status, including token information in the <em>response body</em> for both <em>savings</em> and <em>current account</em> customers.</p><h3>What’s Next</h3><p>In <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-14-e0c5782a685c"><strong>part-14 </strong></a>of this Blog , we covered the following;</p><p>• Testing the token generation API of Keycloak via Insomnia client tool.</p><p>• Configuring <em>Kong Insomnia tool</em> with <em>environment</em> variables for <em>request</em> <em>body</em> and <em>auth</em> details to send an API call to the <em>token generation</em> API <em>endpoint</em> of <em>Keycloak</em> and test the <em>token API</em> for both <em>savings</em> &amp; <em>current account</em> customers.</p><p>• Testing<em> the token API</em> request by sending a <em>POST </em>request to generate <em>tokens</em> for <em>Banking</em> Customers.</p><p>Visit <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-13-d6328d3aea7a"><strong>part-13</strong></a> of the Blog, to use the <em>decK</em> tool to implement APIOps, check for drift in Kong configuration changes &amp; execute Bash scripts to automate the deployment of Banking service into Kong Konnect Control Plane and then into Kong Data Plane with OpenID connect and request-transformer-advanced plugins applied on the Banking service.</p><p>Next, in <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295"><strong>part-15</strong></a> of the Blog we shall test <em>Banking service</em> API onboarded to Kong Gateway in Konnect using Kong Insomnia tool. In <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295"><strong>part-15</strong> </a>of the Blog we will also test the Bank API using <em>Kong Insomnia tool</em> both for <em>savings</em> &amp; <em>current account</em> customers via Kong Gateway, and also test the <em>Banking</em> API using <em>request chaining &amp; pre-request</em> scripting features of <em>Kong Insomnia</em> tool.</p><p>Let’s dive into <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295"><strong>Part-15</strong></a> of the Blog: <a href="https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295">https://medium.com/@shubhojit.dasgupta/dynamic-routing-transformations-part-15-d9b519b3a295</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e0c5782a685c" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>