See what makes Kong the fastest, most-adopted API gateway
Check out the latest Kong feature releases and updates
Single platform for SaaS end-to-end connectivity
Enterprise service mesh based on Kuma and Envoy
Collaborative API design platform
How to Scale High-Performance APIs and Microservices
Call for speakers & sponsors, Kong API Summit 2023!
8 MIN READ
In applications built on a system of microservices, developers should always be on the lookout for opportunities to eliminate unnecessary use of resources, such as database queries, network hops or service requests. API gateway cache (or response caching) is an excellent place to start.
For many microservices, identical requests sent within a window of time will yield identical responses. For example, consider a request to an Orders API for the list of orders submitted yesterday. The first request should be processed, and any necessary services or database queries should be called, but the final response should be cached. Any subsequent requests for the rest of the day should simply return the cached result, thereby saving resources.
If Kong Gateway fronts your upstream services, you can access a reverse proxy cache implementation through the Proxy Cache plugin. This post will walk through setting up and using the plugin, demonstrating response caching as Kong Gateway sits in front of a simple API server.
Let’s start with a quick overview of some core tech concepts for this walkthrough.
Kong Gateway is a powerful and flexible API gateway optimized for microservices and distributed architectures. It sits in front of your upstream services and can handle authentication, load balancing, traffic control, transformations and other cross-cutting concerns through its rich library of plugins.
Webinar: Scaling High-Performance APIs and Microservices
Reverse caching (also known as reverse proxy caching) is a caching implementation in which a dedicated caching application (the reverse proxy) sits in front of the service to be cached. Requests to the service first go through the reverse proxy, which then decides whether to forward the request to the service or respond to the request with a cached response. The decision to return a cached response or forward for a fresh response depends on cache settings, such as the time-to-live (TTL).
The Proxy Cache plugin for Kong Gateway is a built-in plugin that can be enabled by configuration, essentially giving Kong Gateway the role of the reverse proxy.
To demonstrate the Proxy Cache plugin, we’ll build a simple Node.js Express API server with a single endpoint. The endpoint serves up a random programming quote returned by the Programming Quotes API. The server also logs a statement to the console every time its endpoint is hit.
We will use Kong Gateway to sit in front of our service, but we’ll set up two separate routes—one with caching and one without caching—which both forward to our API server.
When we send requests to the /quote
path, which is our uncached route, Kong Gateway will simply forward those requests to our API server.
Requests to the /quote-of-the-minute path, which is our cached route, will also be forwarded to our API server when necessary. We’ll enable the Proxy Cache plugin for this route, configuring Kong Gateway to cache the response for one minute. Subsequent requests to this path will return the cached response until a minute has passed, which is when the cache expires. Then, we will hit the server endpoint again to retrieve a fresh response.
Webinar: How to Protect your Mission Critical APIs and Services Efficiently
Let’s start by building our API server, which fetches and returns a random programming quote. First, we create a project folder, initialize a project with yarn, and then add our dependencies:
~$ mkdir project && cd project ~/project$ yarn init ... ~/project$ yarn add express axios ...
With our project initialized, we create a new file called index.js. The contents of the file are as follows:
const axios = require('axios'); const express = require('express'); const app = express(); const PORT = 8080; let requestCount = 0; app.get('/', async (req, res) => { requestCount++; console.log(Request: ${requestCount}); const result = await axios({ method: 'GET', url: 'https://programming-quotes-api.herokuapp.com/quotes/random' }) const { author, en: quote } = result.data; res.send("${quote}" - ${author}); }) const server = app.listen(PORT, () => { console.log('Listening on port %s', PORT); });
Request: ${requestCount}
"${quote}" - ${author}
Let’s briefly explain what happens in this file:
In our terminal, we run node index.js to start our API server.
In a separate terminal, we use curl to send several requests to our API server.
~$ curl localhost:8080 "Coding is "90 percent finished" for half of the total coding time. Debugging is "99 percent complete" most of the time." - Fred Brooks ~$ curl localhost:8080 "A computer shall not waste your time or require you to do more work than is strictly necessary." - Jef Raskin ~$ curl localhost:8080 "Within a computer, natural language is unnatural." - Alan Perlis ~$ curl localhost:8080 "Nobody knows how to build really complicated hardware systems, so designing hardware tends to be simpler. Software is much more complicated." - Butler Lampson
Looking back at our terminal window with the API server running, this is what we see:
~/project$ node index.js Listening on port 8080 Request: 1 Request: 2 Request: 3 Request: 4
Excellent. Our API server is running as expected. We’ll restart it to reset the request counter, and we’ll leave it running in our terminal window. Now, it’s time to set up Kong Gateway.
The exact steps for installing Kong Gateway will depend on your platform and environment. After you’ve installed Kong Gateway, we have a few additional setup steps to take.
For this particular project, as we use the Proxy Cache plugin, we can configure Kong Gateway with a DB-less declarative approach. That means we can establish all of our configuration upfront in a declarative YAML file, which Kong Gateway will read when it starts.
In your project folder, create an initial declarative configuration file with the following command:
~/project$ kong config init
This will generate a kong.yml file. So far, your project folder should look like this:
~/project$ tree -L 1 . ├── index.js ├── kong.yml ├── node_modules ├── package.json └── yarn.lock 1 directory, 4 files
We’ll return to our kong.yml file shortly.
The kong.conf file is the main configuration file that Kong looks to for startup options. When you first install Kong Gateway, you’ll see a file called kong.conf.default in the /etc/kong folder. Copy that file to a new file called kong.conf. Then, make the following edits to kong.conf:
# PATH: /etc/kong/kong.conf # Around line 953, uncomment and set to off database = off # Around line 1137, uncomment and set to # absolute path to project's kong.yml file declarative_config = /PATH/TO/MY/PROJECT/kong.yml
Now, upon startup, Kong will look to our project’s declarative configuration YAML file.
Let’s return to our declarative configuration file to set up an upstream service—that’s our API server—and a route. We edit the kong.yml file in our project folder so that it looks like this:
_format_version: "2.1" _transform: true services: - name: quote-service url: http://localhost:8080 routes: - name: quote-route-no-cache service: quote-service paths: - /quote
In our declarative configuration file, we’ve set up an upstream service (called quote-service) that points to the URL of our API server (http://localhost:8080). Next, we’ve set up a route to have Kong listen for requests on the /quote path. Kong will forward those requests to our upstream service.
With our configuration in place, we can start Kong:
~$ sudo kong start Kong started
Next, we can send a request to our Kong proxy server, to the /quote path:
~$ curl localhost:8000/quote "No code is faster than no code." - Kevlin Henney
Great! It looks like Kong Gateway forwarded our request to our API server, and we’ve received the expected response. When we look at the terminal window with our API server running, this is what we see:
~/project$ node index.js Listening on port 8080 Request: 1
Everything is running as expected.
Next, we’ll add another route to our declarative configuration file, and we’ll enable the Proxy Cache plugin on that route. We edit kong.yml so that it looks like the following:
_format_version: "2.1" _transform: true services: - name: quote-service url: http://localhost:8080 routes: - name: quote-route-no-cache service: quote-service paths: - /quote - name: quote-route-with-cache service: quote-service paths: - /quote-of-the-minute plugins: - name: proxy-cache route: quote-route-with-cache config: cache_ttl: 60 strategy: memory content_type: - text/html; charset=utf-8
Notice that we have added another route, called quote-route-with-cache. Kong will listen for requests on the /quote-of-the-minute path and forward those requests—just like it does for the /quote path—to our upstream service.
In addition, we’ve added a plugin. The name of this plugin is proxy-cache, and we’ve enabled it specifically on the route called quote-route-with-cache. We configure this plugin with a TTL of 60 seconds.
Since we have updated our declarative configuration, we need to restart Kong:
~$ sudo kong restart Kong stopped Kong started
Now is the moment of truth. With our Proxy Cache plugin in place, this is what we expect to happen:
This is what it looks like when we send our requests:
When we sent four requests in rapid succession, we received the same response. Looking at the terminal window for our API server, we see that the request counter has only incremented one time, despite our four calls:
~/project$ node index.js Listening on port 8080 Request: 1 Request: 2
After waiting for a minute, we send more requests to the /quote-of-the-minute path.
As expected, our first new request receives a new programming quote as a response. The subsequent two requests receive the same quote again, which is the cached result.
When we check our API server window, we see that the request counter has, again, only incremented one time:
~/project$ node index.js Listening on port 8080 Request: 1 Request: 2 Request: 3
Our Proxy Cache plugin is working exactly as expected!
Technical Guide: Secure Your Web, Mobile Applications and APIs using the Kong Gateway
In our demo, we enabled the Proxy Cache plugin on a specific route. However, we could enable the plugin on an entire service or on a consumer, which is a specific user. For example, we can also enable the plugin on the combination of a consumer and a route, which would narrow the plugin’s scope.
In our demo example, the response to /quote-of-the-minute would be the same for all users sending requests within the one-minute window. If we enabled the plugin at the consumer level instead, with each consumer authenticating with a unique API key or JWT, each user would have their own “quote of the minute” cached, and that quote would not be the same as what a different user gets cached.
Response caching for your microservices is a simple and effective tactic for optimization. By using a reverse proxy to decide whether to handle requests by forwarding for a fresh response or by using the cache, you can reduce the load on your network and your services. With Kong Gateway, getting up and running with response caching is quick and simple with the Proxy Cache plugin.
Share Post
Learn how to make your API strategy a competitive advantage.