How I Made My Next.js App Resilient After Vercel's API Fetching Time Limits

How I Made My Next.js App Resilient After Vercel's API Fetching Time Limits

Sandipan Das
Sandipan Das |
6 min read5 views
twitterfacebooklinkedinpinterestW

A few months ago, I was working on a Next.js project for a client. Everything was going smoothly—pages were loading fast, data flowed seamlessly, and my API calls were rock solid. Or so I thought.

One morning, I woke up to a frantic message:

"Hey! The app isn’t loading data properly. It’s just… blank. Clients are complaining. Please check it ASAP!"

That’s when the nightmare started.

The Root of the Problem

After digging into the logs, I noticed several API calls failed due to intermittent server issues. Usually, these calls would self-correct after a page refresh or two, but this time, they weren't.

What made things worse? Vercel had recently introduced stricter time limits on API requests. You were out of luck if your API call didn't return within a specific window. Boom. Failure. No retries, no second chances.

And, of course, this happened on the day the API I was using was acting up.

The "Aha!" Moment

I knew I couldn't keep relying on a "hope-it-works" strategy. I needed a way to make my API calls more resilient. What if, instead of immediately failing when an API call hit a bump, my app could pause, retry, and try again?

That's when the idea for fetchWithRetry was born—a simple function that would give my app the power to recover from transient API failures without breaking a sweat.

Building fetchWithRetry: A Resilient API Fetcher

I sat down, brewed a strong cup of coffee, and got to work. My mission? To create a function that could:

  1. Retry failed API calls a specific number of times.
  2. Wait a few seconds between retries to give the server a chance to recover.
  3. Throw an error only after all retries have been exhausted.

After a few hours of tinkering, I had this:

const fetchWithRetry = async (
    fetchFunction: () => Promise<any>,
    maxRetries: number = 3,
    delay: number = 4000
): Promise<any> => {
    let retries = maxRetries;
    while (retries > 0) {
        try {
            return await fetchFunction(); // Try the API call
        } catch (error) {
            retries -= 1; // Reduce the retry count
            if (retries === 0) {
                // All retries failed
                throw new Error("Failed to fetch data after multiple retries.");
            }
            console.warn(
                `Fetch failed. Retrying... (${maxRetries - retries}/${maxRetries})`
            );
            // Wait before retrying
            await new Promise((resolve) => setTimeout(resolve, delay));
        }
    }
};
export { fetchWithRetry };


How It Saved My App

I plugged this function into my Next.js project. The first test was in getServerSideProps, where the app fetched data for server-side rendering.

The New getServerSideProps

import { fetchWithRetry } from "./utils/fetchWithRetry";


export const getServerSideProps = async () => {
    try {
        const data = await fetchWithRetry(async () => {
            const res = await fetch("https://api.example.com/data");
            if (!res.ok) throw new Error("Failed to fetch");
            return res.json();
        });
        return { props: { data } };
    } catch (error) {
        console.error("Error fetching data:", error.message);
        return { props: { data: null } };
    }
};

The difference was night and day. If an API call fails once, the app will try again. And again. And—if necessary—a third time. The data loaded without a hitch if the server recovered within those attempts. There are no blank screens. No angry clients.

A Real-Life Scenario

Let me walk you through how this works in practice.

Imagine your app calls an API to fetch weather data for a user's location. The API server might return an error or timeout on a bad day due to high traffic. Without retry logic, your app would fail immediately, leaving users stuck.

With fetchWithRetry, here's what happens:

  1. First Attempt: The app makes the API call. The server is unresponsive—result: Retry #1.
  2. Second Attempt: The server is still struggling, but it's starting to recover—result: Retry #2.
  3. Third Attempt: The server responds successfully, and the app loads the data. Result: Problem solved without the user noticing a thing.

Lessons Learned

Here's what I realized after implementing fetchWithRetry:

  1. Retry Logic is Essential; downtime or missing data can impact your users in production apps.
  2. Delays Make a Difference: Giving the server a moment to recover often resolves transient failures.
  3. Exponential Backoff is Next-Level: For even better results, you can increase the delay with each retry (e.g., 2 seconds, then 4 seconds, then 8 seconds).

The Payoff

Thanks to this simple function, my Next.js app became much more resilient. The blank screens disappeared, my client was happy, and I could finally sleep at night knowing my app could handle hiccups gracefully.

If you're building a Next.js app and you're worried about API failures—especially with Vercel's time limits—give fetchWithRetry a try. It might just save you a frantic call from your client one day.

Final Thoughts

Have you ever faced challenges with API failures in your apps? Share your story with me by scheduling a meeting, and let's talk about how we can build stronger, more reliable applications together. 🚀

twitterfacebooklinkedinpinterestW

Join & Grow

Be Part of a Winning Community!
Let’s Connect, learn, and succeed with like-minded people. Follow now!

Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image
Image

+100s of Happy Clients!

Thanks for checking out my portfolio!

I really enjoy programming—it's not just my job, it's something I love. I've finished lots of web projects using different tools, and I'm excited to share what I know with everyone and help out.

I know my way around ReactJS, NextJS, MongoDB, WordPress, Laravel, CodeIgniter, and making things look good (UI/UX). I'm also a quick learner, always ready to learn and grow in my field.

If you've got any questions or need some help, feel free to get in touch anytime.

Best Regards,

SANDIPAN DASFull Stack Web Developer

Let‘s collaborate
on your next project

Chat on WhatsApp
Schedule a Zoom Meeting