Make your apps cost efficient by caching APIs
Tags: api, caching, webdev, opensource
Published: 2022-12-22 21:52:55

**Author:** Nathaly Toledo
**We discuss**
    - The way to store the cache
    - When to invalidate the cache and the lifetime of a cached response

### **Context**


When we are working on an app, it is not strange to rely on [APIs](<https://aws.amazon.com/what-is/api/#:~:text=API%20stands%20for%20Application%20Programming,other%20using%20requests%20and%20responses.)> to get the information we need for our own apps. Sometimes, however, that data we require comes at a price in the form of credits. If the data we require from the API is unlikely to change, we can cache the response and return a stored version of what we would get in a real API call. For example, consider an API that gives you the capital cities of each country. How likely is the capital city of a country to change in an hour? Highly unlikely. For that reason, we can explore a caching option.

The case we will discuss today focuses on the Amplify repository, an open-source project that provides a platform for citizens to engage in causes that matter to them and amplifies their voices via the automation of their participation. The project uses a paid API, Cicero, that retrieves government officials' data. Each call cost you 1 to 2 credits. Since the representatives’ information is unlikely to change, we want to reduce the number of calls made to the API.

To accomplish this, we will use the library [axios-cache-interceptor](<https://github.com/arthurfiorette/axios-cache-interceptor>) to “cache API calls to reduce the number of credits we use”. For this caching option we need to see the lifetime of a cached response, a way to persist the day permanently and across different user sessions and, keep in mind, the margin to consider for cutting expenses.


We have compared several libraries and have decided to work with the axios-cache-interceptor for the following reasons:


### 
**List of libraries we have compared:**
- axios-cache-plugin
- cachios
- axios-cache-adapter
- axios-cache-interceptor 
- [axios-cache-plugin - npm](https://npmjs.com/package/axios-cache-plugin)
- [cachios - npm](https://npmjs.com/package/cachios)
- [axios-cache-adapter - npm](https://npmjs.com/package/axios-cache-adapter)
- [axios-cache-interceptor - npm](https://npmjs.com/package/axios-cache-interceptor)
- Reputation/popularity
    
    Reputation or popularity across time is an important measure because it allows you to get a reference of the level of trust given to users over time. A widespread tool may not be a solid indicator of code quality alone, at least not in all cases. Yet, one of the factors to a tool becoming popular and sustaining or improving its popularity and download rate over time includes its usability and user preference over a product. I am not including the references here, but many developers in forums recommend the “popular tools” and indicate them as an alternative or good solution for a problem. By recommending them, they contribute to popularity.
    
    Source: [https://npmtrends.com/axios-cache-adapter-vs-axios-cache-interceptor-vs-axios-cache-plugin-vs-cachios](https://npmtrends.com/axios-cache-adapter-vs-axios-cache-interceptor-vs-axios-cache-plugin-vs-cachios)
    
- Maintenance frequency and status
    
    We take it as a value for comparison because a code that is maintained regularly and attends to the user’s needs, as well as relevant feedback, will be less prone to errors. The code can be more robust if it responds to such demand. We will measure it by the number of issues opened (that remain open/have not been solved) and the last time the repository was updated:
    
- Features
    
    The features yielded a harder comparison since it was preferred that I had a better experience with each one, before the preliminary research. However, given that fully testing each library with the relevant features would take me 2 days of experimenting with each, I decided to look for similar and trusted sources of comparison. The references I am using are from the axios-cache-interceptor analysis and comparison page: [https://axios-cache-interceptor.js.org/#/pages/comparison](https://axios-cache-interceptor.js.org/#/pages/comparison)
    
- Ease of use
    
    axios-cache-interceptor was easier to set up and install, less verbose, and more intuitive, it took me 5 min to set up everything and get a response. With axios-cache-adapter, it took 10-15 min and I could not install it with the project, but the response took just slightly more time to be returned.
    

### **The implementation**

**Here are some Important questions you may need to ask before implementing the caching:**

- How is this done via Node?
- When should I, if ever, invalidate the cache?
- *	Development**
- *	Requirements**
- Node.js
- An API, I will be using the Cicero API.
- A code editor. I will use Visual Studio Code.

1. **Create directory**
```
mkdir hello-cache
cd hello-cache
```

2. **We install express, axios and axios-cache-interceptor**

`npm install express axios-cache-interceptor`

3. *Create a new file inside the folder called app.js **

4. **Add the following contents**

![setupCache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xyq1dj1ntntg9m3c0302.png)


5. **Run the app**
Command: node app.js
```
To define a limit or deadline for a cached response to be valid and updated, we make use of the property "ttl", as part of the “per request configuration”. We set it to the reasonable time limit of 1 week in milliseconds: 604800000.

// The time until the cached value is expired in milliseconds.

    ttl: 1000 * 60 * 10080,

```

- *Source: **[https://axios-cache-interceptor.js.org/#/pages/per-request-configuration?id=cachettl](https://axios-cache-interceptor.js.org/#/pages/per-request-configuration?id=cachettl)

```
**Some aspects to understand about the storage configuration and advanced properties**

The lifetime of a request will only make sense and work if we use persistent storage. There are several options they provide, such as

```

1. In memory: that will not be persistent and will easily be lost with a page reload.
2. Web storage: it has sessions and across sessions (works with a browser Window and dies as soon as it is closed)
3. Custom storage: which can last more time.
    
    I am not considering using a database. Instead, I think we can use documents that are stored in the file system for persistence or variables that are initialized.
    
    **Demo video:**
    
    - *[https://www.loom.com/share/48330ede3a394ffc9aff5a539eae17a4](https://www.loom.com/share/48330ede3a394ffc9aff5a539eae17a4) **

### **Conclusions**

**Results and the effect of this implementation**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nsr1akrf47o9exbdyik7.png)




```
The image above is the actual user dashboard of the Cicero API account. On average, we could assume that I make 9 calls per day, with a total of 63 calls per week. If we are only making real API calls (updating the cache) once a week, that is, only making one call to the API per week, we are using, roughly, 1.58% of the current average. For that case, we would be cutting 98.5% of our weekly use.

Maybe we can pay as many credits as we may need to sustain hourly API calls from millions of users across different sessions, but our work as developers also involves using resources (time, memory, and money) efficiently. If it is not necessary, it should not be there. Today, we explore an option to refactor our project and cut costs when possible,

```

### **References**:

*Ahn nath/cache option apis by ahn-nath · Pull Request #373 · ProgramEquity/amplify*.     (2022, November). GitHub. [https://github.com/ProgramEquity/amplify/pull/373](https://github.com/ProgramEquity/amplify/pull/373)