When deploying a project to Vercel, it is critical to abide by the Fair Use Policy or your Enterprise agreement (email your Customer Success Manager for further information). The Usage Dashboard is the most important page to check the usage of your projects. Another useful tool to monitor requests and errors is the Function Logs tab as it can provide logging output for your Serverless Executions.
Definitions
Before we outline possible solutions for high usage of Serverless Functions, we need to define a few concepts that are relevant.
- Serverless Invocation: When a Serverless Function is triggered by an event. Those events are typically requests that will be processed by the function.
- Serverless Execution: The process of executing a Serverless Function, which is triggered by an invocation.
- Serverless Function memory: The size of the memory allocated to the function. For further information, you can refer to the Configuration Reference.
- GB-Hrs: The unit of measurement for Serverless Execution. If one function with 1024MB allocated takes one second to process a request, we can conclude it used 1GB-Seconds, which is (1/3600)GB-Hrs. For further information, check the article "What are GB-Hrs for Serverless Function Execution?".
With Edge Functions
We recommend migrating your project's Serverless Functions to Vercel's Edge Functions to reduce latency and provide faster response times. Edge Functions run on our lightweight Edge Runtime which is more performant and cost-effective than Serverless Functions on average. Edge Functions are deployed globally on our Edge Network, and can automatically execute in the region nearest to the user who triggers them. They also have no cold boots, which means they don't need extra time to start up before executing your code.
With Next.js
Next.js is a framework that gives your team the flexibility to choose between different rendering methods:
- Static Site Generation (SSG) allows you to generate static content at build time. Used through
getStaticProps
inside of Next.js. - Incremental Static Regeneration (ISR) allows you to create or update content without redeploying your site. Used through
getStaticProps
andrevalidate
inside of Next.js. - Server-Side Rendering (SSR) allows you to render pages dynamically on the server. This is useful for pages where the rendered data needs to be unique on every request. Used through getServerSideProps inside of Next.js.
It's possible to reduce your Serverless Function usage with all the rendering methods above. Even API Routes can use the Vercel CDN to cache responses and serve content directly from the edge for optimal speed.
Static Site Generation
If your page can use SSG instead of SSR, it is recommended that you implement this approach to lower the usage of Serverless Executions. The page will be generated a single time at build-time, and it is not possible to regenerate it or replace its content after the build. Since your app will no longer execute a function for every page request, which is true for uncached SSR pages, the amount of Serverless Executions for pages using SSG is 0 GB-Hrs.
Incremental Static Regeneration
In case a specific page needs to be regenerated periodically due to dynamic data, you can use ISR to lower the number of Serverless Executions performed by your app. With this strategy, your pages will be statically generated and cached in the Vercel CDN. A Serverless Function will be triggered after a certain interval to refresh the content of the cache. By using ISR, you will lower the amount of Serverless Executions used by your app in comparison with uncached SSR pages. Your users will also benefit from the speed improvements that ISR will give since your deployment will serve content directly from the Vercel CDN.
CDN Caching and stale-while-revalidate
If you are unable to implement ISR or SSG, you can use caching headers to store SSR pages in the Vercel CDN. One of the best headers is stale-while-revalidate
, which is used to serve stale content while the cache is refreshed in the background. You can see an example of the header being used in a Next.js SSR page below. Do notice you can also use this header for Next.js API routes. If you need to apply the header to multiple paths, using the Next.js headers configuration is also an option.
1export async function getServerSideProps(context) {2 const res = await fetch(`https://...`)3 const data = await res.json()4 5 context.res.setHeader('Cache-Control', 's-maxage=600, stale-while-revalidate=30') // set caching header6
7 return {8 props: {}, // will be passed to the page component as props9 }10}
1export default function handler(req, res) {2 res.setHeader('Cache-Control', 's-maxage=600, stale-while-revalidate=30') // set caching header3 res.status(200).json({ name: 'John Doe' })4}
1// next.config.js2module.exports = {3 async headers() {4 return [5 {6 source: '/example/:id',7 headers: [8 {9 key: 'cache-control',10 value: 's-maxage=600, stale-while-revalidate=30',11 },12 ],13 },14 ]15 },16}
In the example above we are telling the Vercel CDN the content is fresh for 600 seconds, and it may continue to be served stale for up to an additional 30 seconds while an asynchronous validation is attempted by triggering a Serverless Function. If validation is inconclusive, or if there is not traffic that triggers it, after 30 seconds the stale-while-revalidate function will cease to operate, and the cached response will be "truly" stale (i.e., the next request will block and be handled normally).
Generally, you may want to use a combination of s-maxage and stale-while-revalidate to the longest total potential freshness lifetime that they can tolerate. For example, with both set to 600, the server must be able to tolerate the response being served from cache for up to 20 minutes. Since asynchronous validation will only happen if a request occurs after the response has become stale, but before the end of the stale-wile-revalidate window, the size of that window and the likelihood of a request during it determines how likely it is that all requests will be served without delay. If the window is too small, or traffic is too sparse, some requests will fall outside of it, and block until the deployment can validate the cached response.
The text above was inspired by RFC5681.
With Serverless Functions in /api
If you are not using Next.js, you can still implement some strategies to lower the amount of resources used by your deployment.
CDN Caching and stale-while-revalidate
If your API is returning data that can be shared publicly (without authorization headers or cookies), you can use caching headers to cache the response of the function in the Vercel CDN. One header that we can highlight is stale-while-revalidate
.
1module.exports = (req, res) => {2 res.setHeader('Cache-Control', 's-maxage=600, stale-while-revalidate=30') // set caching header3 res.status(200).json({ name: 'John Doe' })4}
Configuring your Serverless Functions
It is possible to customize the amount of memory used by your Serverless Functions. If your function is I/O bound and needs to wait on upstream providers often, lowering the memory size allocated to it is a good strategy to reduce the overall GB-Hrs used by your deployment. Do notice that the CPU power of your Serverless Executions is directly related to the amount of memory configured to your functions. Therefore, for processing-intensive functions, lowering the memory size is not advised.
Another important configuration is the Regions for your Serverless Functions. If you don't deploy close to upstream dependencies or providers, it is possible that the response time of your functions is being affected by latency. By deploying closer to your Database or API, you will observe that your functions will take lower to process a request, reducing your Serverless Executions usage overall.
You can read more about how to configure your functions in the Configuration Reference.
1{2 "functions": {3 "api/example.js": {4 "memory": 128,5 "maxDuration": 106 }7 }8}
Moving APIs to serverful providers
Using Vercel for API-intensive work may not be a good strategy. Depending on your workload and other variables associated with your application, hosting only the frontend on Vercel can help you reduce your Serverless Execution usage.