Caching API Queries in Node
When making API queries to a third party, there may be cases where the API endpoint returns relatively static data. In those cases, the performance of your app will benefit from caching the data. Let’s try querying this Pokemon API called PokeAPI for a list of Pokemon, and add caching.
Here’s some code querying an endpoint that returns the first 20 Pokemon out of 811. This list is unlikely to change frequently. Not only that, but the API imposes a limit of 300 requests per resource per IP address. Therefore, if many clients accessed the server, we’d be denied pretty quickly!
The solution? We can take the response and cache it in memory so there’s no need to make the API call again and again.
The node-cache module is a great cache solution for storing cached data in memory. After instantiating an instance of node-cache, .set and .get methods can be used to add/retrieve objects.
Note that this article will use arrows, let, and const. These ES6 features are available in Node 4.x and higher.
Before incorporating node-cache and the API call, we need to consider the scenarios where a user tries to access data. Either the data is in the cache, or it’s not.
- If data is cached, calling `cache.get` will give us a valid object. We can return the data without accessing the API endpoint.
- If the data is not cached, calling `cache.get` will give us an invalid object. We can access the API endpoint and store the data in the cache using `cache.set`. The next time a user accesses the endpoint, they’ll get cached data!
Caching multiple API endpoints
Currently, our code uses a static string to identify the data stored in the cache. But what if we have multiple endpoints, or endpoints that contain user input, like query parameters? Examples:
In order to cache multiple endpoints, we could use the URL itself as the key and create a direct mapping between the URL and the data. This URL would replace `my-pokemon` in the code above.
Although our code is fairly concise, it’s not very reusable. It’d be very beneficial to create a function allowing us to cache any API query, and perhaps include promises or callbacks to pass data along to another function instead of printing it out. Here’s an example. It’s not perfect, but it shows how you can modularize this code and have it work with a variety of GET endpoints. Not just Pokemon!
Updating and invalidation
What if we have data that changes? Node-cache provides additional options to set the expiration time for a cached object.
Caching API queries in Node can be implemented in many different ways. While Redis and memcached provide more durable solutions for production applications, node-cache is a great module to play with in smaller applications. Some things you may want to try may include writing tests for these examples, or perform benchmarks to measure speed improvements.
If you enjoyed this article or found value in it, I’d highly appreciate a recommendation or share. Feel free to comment if there are any questions or errors, and happy coding!