DEV Community

Cover image for Cache a response in Vercel using SSR and serverless functions in SvelteKit
Arnau Espin
Arnau Espin

Posted on • Edited on

Cache a response in Vercel using SSR and serverless functions in SvelteKit

TLDR

I will show how we can cache the response of an API using Vercel caching and a serverless function (function that is executed during Server Side Rendering in this case and not on client). In this case of the BTCUSD price obtained from a call to the Binance API.

Introduction

Hello and welcome to my second post. Today, I will show you how we can cache the response of a function that runs on the server (Vercel in this case) to optimize the number of calls this functiom does to an external API. This means that the API call will be done on the server and not on client, reducing the payload of the user accessing the website.

Application

Let's suppose we have a website that everytime is rendered it fetches the price of Bitcoin from the Binance API. This means that everytime a user accesses our site, it fetches data from the Binance API. If we have 100 visits in 1 minute, from visit 50th on, the user will get a 429 HTTP ERROR (too many requests). Is it needed to call the API multiple times to obtain BTCUSD price which will barely change during those seconds? - Probably not.

So let's see how we can solve this by caching the BTCUSD price on Vercel. Let's suppose we have 3 clients that access our website, the first one will be the one that calls the serverless function and caches the response for that function for 3600seconds.
What we're attempting to do

Code

In this case we only want to cache the response if we actually get a price number from the Binance API. We can use bodyShouldBeCacheable or any other valid method.

// src/routes/api/btcusd.ts
import type { RequestHandler } from '@sveltejs/kit'

const BTCUSDT= 'https://api1.binance.com/api/v3/ticker/price?symbol=BTCUSDT'

export const get: RequestHandler = async () => {
    const getBtcUsdtPrice = async (): Promise<number | undefined> => {
         try{
             const data = await fetch(BTCUSDT)
             const { price } = await data.json()
             return price
         } catch(err) {
             return undefined
         }
    }

    const body = await getBtcUsdtPrice()
    const bodyShouldBeCacheable = !isNaN(body)

    return {
        status: 200,
        body,
        headers: {
            'Cache-Control': bodyShouldBeCacheable 
             ? 'max-age=3600, public' 
             : 'no-cache',
        },
    }
}

Enter fullscreen mode Exit fullscreen mode
// src/routes/index.svelte

const btcPrice: Writable<number> = writable(0)

const fetchAndUpdateExchanges = async () => {
    const response = await fetch('/api/exchanges')
    const btcPriceData= await response.json()
    btcPrice.set(btcPriceData)
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Using SSR is always good choice to reduce the amount of data the end user is downloading to render your site, specially if running on mobile phone with limited data to use, or slow connections.
On the other hand Vercel will not let you render data on server for free (completely) forever, so, caching a response will also aid your pocket!

You can follow me on:

Top comments (0)