Runtime Logs Don't Show Internal API Requests

Hello everyone;

I’ve noticed that Vercel runtime logs don’t show internal API request or related function console logs. I created a cron job for my project that calls the /api/fetch-transaction endpoint to fetch transaction data from BSC Scan and cache it on the server daily. I also use CRON_SECRET for security with middleware, and it is working correctly.

Project Details:

  • Framework: Next.js 14
  • Run engine: Node.js 20

Problem Occurrence:

  • Situation: Cron-job making internal API calls.

However, when I build the cron job endpoint, the fetch logs appear correctly in the build logs:

[14:27:10.135]    Collecting page data ...
[14:27:13.581]    Generating static pages (0/16) ...
[14:27:13.879]    Generating static pages (4/16) 
[14:27:14.132] Cron job endpoint called
[14:27:14.133] Cron job started
[14:27:14.141]    Generating static pages (8/16) 
[14:27:14.394] Fetching transactions for testnet address: 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4
[14:27:14.394] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4&testnet=true&allTx=true&cleanCache=true
[14:27:15.058]    Generating static pages (12/16) 
[14:27:15.063] Response status: 200
[14:27:15.063] Transactions fetched for 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4
[14:27:15.063] Successfully fetched transactions for testnet address: 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4
[14:27:15.520] Fetching transactions for testnet address: 0x9eB947Be4de53332022Edbc51528d33EB5D80f94
[14:27:15.520] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0x9eB947Be4de53332022Edbc51528d33EB5D80f94&testnet=true&allTx=true&cleanCache=true
[14:27:15.952] Response status: 200
[14:27:15.952] Transactions fetched for 0x9eB947Be4de53332022Edbc51528d33EB5D80f94
[14:27:15.952] Successfully fetched transactions for testnet address: 0x9eB947Be4de53332022Edbc51528d33EB5D80f94
[14:27:16.411] Fetching transactions for testnet address: 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6
[14:27:16.411] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6&testnet=true&allTx=true&cleanCache=true
[14:27:16.888] Response status: 200
[14:27:16.889] Transactions fetched for 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6
[14:27:16.889] Successfully fetched transactions for testnet address: 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6
[14:27:17.364] Fetching transactions for testnet address: 0x891F52b828C7242dC95D38903D387D7d12e33CB2
[14:27:17.365] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0x891F52b828C7242dC95D38903D387D7d12e33CB2&testnet=true&allTx=true&cleanCache=true
[14:27:17.656] Response status: 200
[14:27:17.656] Transactions fetched for 0x891F52b828C7242dC95D38903D387D7d12e33CB2
[14:27:17.656] Successfully fetched transactions for testnet address: 0x891F52b828C7242dC95D38903D387D7d12e33CB2
[14:27:18.120] Fetching transactions for mainnet address: 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0
[14:27:18.120] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0&testnet=false&allTx=true&cleanCache=true
[14:27:18.988] Response status: 200
[14:27:18.988] Transactions fetched for 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0
[14:27:18.988] Successfully fetched transactions for mainnet address: 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0
[14:27:18.988] Fetching transactions for mainnet address: 0xbe2D8AC2A370972C4328BED520b224C3903A4941
[14:27:18.988] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0xbe2D8AC2A370972C4328BED520b224C3903A4941&testnet=false&allTx=true&cleanCache=true
[14:27:19.037] Response status: 200
[14:27:19.037] Transactions fetched for 0xbe2D8AC2A370972C4328BED520b224C3903A4941
[14:27:19.037] Successfully fetched transactions for mainnet address: 0xbe2D8AC2A370972C4328BED520b224C3903A4941
[14:27:19.537] Fetching transactions for mainnet address: 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C
[14:27:19.538] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0x55b6d96126879Fe99ca1f57A05F81941d0932F9C&testnet=false&allTx=true&cleanCache=true
[14:27:19.967] Response status: 200
[14:27:19.967] Transactions fetched for 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C
[14:27:19.967] Successfully fetched transactions for mainnet address: 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C
[14:27:20.722] Fetching transactions for mainnet address: 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce
[14:27:20.722] Fetching transactions from URL: https://tokens-ui-nextjs-q1a2qsube-tahsins-projects-0ae86724.vercel.app/api/fetch-transactions?contractaddress=0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce&testnet=false&allTx=true&cleanCache=true
[14:27:20.722] Response status: 200
[14:27:20.722] Transactions fetched for 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce
[14:27:20.722] Successfully fetched transactions for mainnet address: 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce
[14:27:21.060] Cron job finished
[14:27:21.061] Cron job completed successfully:  Cron jobs completed with the following results:
[14:27:21.061] Testnet address 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4: Transactions fetched for 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4
[14:27:21.061] Testnet address 0x9eB947Be4de53332022Edbc51528d33EB5D80f94: Transactions fetched for 0x9eB947Be4de53332022Edbc51528d33EB5D80f94
[14:27:21.061] Testnet address 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6: Transactions fetched for 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6
[14:27:21.061] Testnet address 0x891F52b828C7242dC95D38903D387D7d12e33CB2: Transactions fetched for 0x891F52b828C7242dC95D38903D387D7d12e33CB2
[14:27:21.061] Mainnet address 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0: Transactions fetched for 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0
[14:27:21.061] Mainnet address 0xbe2D8AC2A370972C4328BED520b224C3903A4941: Transactions fetched for 0xbe2D8AC2A370972C4328BED520b224C3903A4941
[14:27:21.061] Mainnet address 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C: Transactions fetched for 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C
[14:27:21.061] Mainnet address 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce: Transactions fetched for 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce
[14:27:21.061] 
[14:27:21.062]  ✓ Generating static pages (16/16)
[14:27:21.149]    Finalizing page optimization ...
[14:27:21.149]    Collecting build traces ...
[14:27:21.154] 

When I run the cron job from Settings > Cron Jobs > Run or via Postman, the runtime logs only show this:

Jul 29 14:36:10.16    GET---     tokens-ui.vercel.app/api/cron-jobs     Authorization successful
Jul 29 14:36:10.11    GET200     tokens-ui.vercel.app/api/cron-jobs     [GET] [middleware: "src/middleware"] /api/cron-jobs status=200 

I have run several tests, and it does work correctly by fetching data with the /api/fetch-transaction endpoint. It fetches the data and caches it, but the /api/fetch-transaction endpoint requests never show up in the runtime logs.

Here is the response from the cron-job endpoint when called via Postman:

{
    "message": "Cron jobs completed successfully: ",
    "response": "Cron jobs completed with the following results:
\nTestnet address 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4: Transactions fetched for 0x70aF4c67f16019C13516D814aAf9A6aD74CFd2F4
\nTestnet address 0x9eB947Be4de53332022Edbc51528d33EB5D80f94: Transactions fetched for 0x9eB947Be4de53332022Edbc51528d33EB5D80f94
\nTestnet address 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6: Transactions fetched for 0xdC7B8A96e0Ce131E1C0562BB0Cf35F12a0D1b6d6
\nTestnet address 0x891F52b828C7242dC95D38903D387D7d12e33CB2: Transactions fetched for 0x891F52b828C7242dC95D38903D387D7d12e33CB2
\nMainnet address 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0: Transactions fetched for 0x5D5c5c1d14FaF8Ff704295b2F502dAA9D06799a0
\nMainnet address 0xbe2D8AC2A370972C4328BED520b224C3903A4941: Transactions fetched for 0xbe2D8AC2A370972C4328BED520b224C3903A4941
\nMainnet address 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C: Transactions fetched for 0x55b6d96126879Fe99ca1f57A05F81941d0932F9C
\nMainnet address 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce: Transactions fetched for 0xF9f594D86AEF52644473edC43B6dC9656E4fD2Ce\n"
}

Is this behavior expected on Hobby Account, or should the internal API calls made by the cron job be logged in the Vercel runtime logs? Typically, I would expect these internal API requests to appear in the logs for better monitoring and debugging. Your guidance on whether this is the intended functionality or if there might be an issue would be greatly appreciated.

Here are the related codes:

/app/api/cron-jobs/route.ts

import { NextResponse } from "next/server";
import { runCronJobs } from "~~/services/cron/cronJobs";

export async function GET() {
  console.log("Cron job endpoint called");
  try {
    const response = await runCronJobs();
    if (response) {
      console.log("Cron job completed successfully: ", response);
      return NextResponse.json({ message: "Cron jobs completed successfully: ", response }, { status: 200 });
    } else {
      console.log("No response from runCronJobs");
      return NextResponse.json({ error: "No response from runCronJobs" }, { status: 500 });
    }
  } catch (error) {
    console.error("Error running cron jobs:", error);
    if (error instanceof Error) {
      return NextResponse.json({ error: error.message }, { status: 500 });
    } else {
      return NextResponse.json({ error: "Unknown error" }, { status: 500 });
    }
  }
}

/services/cron/cronJobs.ts

"use server";
import scaffoldConfig from "~~/scaffold.config";

const cronSecret = process.env.CRON_SECRET;
const vercelByPass = process.env.VERCEL_BYPASS;
const testnetAddresses = scaffoldConfig.testnetContractAddressList || [];
const mainnetAddresses = scaffoldConfig.contractAddressList || [];
const baseUrl = process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "https://tokens-ui.vercel.app";

async function fetchTransactions(contractAddress: string, testnet: boolean) {
  const url = `${baseUrl}/api/fetch-transactions?contractaddress=${contractAddress}&testnet=${testnet}&allTx=true&cleanCache=true`;
  console.log(`Fetching transactions from URL: ${url}`);

  const headers: Record<string, string> = {
    Authorization: `Bearer ${cronSecret}`,
  };

  if (vercelByPass) {
    headers["x-vercel-protection-bypass"] = vercelByPass;
  }

  const response = await fetch(url, {
    method: "GET",
    headers,
  });
  console.log(`Response status: ${response.status}`);

  if (!response.ok) {
    console.error(`Failed to fetch transactions: ${response.status} ${response.statusText}`);
    throw new Error(`Failed to fetch transactions for ${contractAddress}`);
  }

  console.log(`Transactions fetched for ${contractAddress}`);
  return `Transactions fetched for ${contractAddress}`;
}

async function delay(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

export async function runCronJobs() {
  console.log("Cron job started");
  let resultMessage = "Cron jobs completed with the following results:\n";

  await delay(500);

  for (const address of testnetAddresses) {
    console.log(`Fetching transactions for testnet address: ${address}`);
    try {
      const message = await fetchTransactions(address, true);
      console.log(`Successfully fetched transactions for testnet address: ${address}`);
      resultMessage += `Testnet address ${address}: ${message}\n`;
    } catch (error) {
      if (error instanceof Error) {
        console.error(`Error fetching transactions for testnet address ${address}:`, error);
        resultMessage += `Testnet address ${address}: ${error.message}\n`;
      }
    }
    await delay(500);
  }

  for (const address of mainnetAddresses) {
    console.log(`Fetching transactions for mainnet address: ${address}`);
    try {
      const message = await fetchTransactions(address, false);
      console.log(`Successfully fetched transactions for mainnet address: ${address}`);
      resultMessage += `Mainnet address ${address}: ${message}\n`;
    } catch (error) {
      if (error instanceof Error) {
        console.error(`Error fetching transactions for mainnet address ${address}:`, error);
        resultMessage += `Mainnet address ${address}: ${error.message}\n`;
      }
    }
    await delay(500);
  }
  console.log("Cron job finished");
  return resultMessage;
}

Thanks for reaching out about this. I shared it with the Cron Jobs team :pray:

Hi tahsin,

I’m an engineer working on cron jobs. Let me reiterate to see if I understood your post correctly:

  1. You’ve set up a cron job under the following route /api/cron-jobs
  2. The cron job will make a fetch request to /api/fetch-transaction
  3. It seems to work at build time, but not at runtime

Invocations made through cron jobs are not too different from normal invocations, so they should appear just like any other request, except if they’re requests for static content.

Checking your fetchTransactions function, it seems like you’re calling fetch without cache: 'no-store'.
While it is true that server actions and API requests with a POST method would not require it, cron jobs are GET requests, so it’ll be necessary.

Could you try to add cache: 'no-store' to the fetch call and see if that will work?
See more here: Building Your Application: Caching | Next.js

Hello @amyegan and @andy. Thank you for your responses. :pray:

As you suggested, I tried to perform cron-jobs fetches using the no-store feature, and all fetch operations started appearing in the runtime logs.

Firstly, I misdiagnosed the issue. I thought that requests to the api/fetch-transactions endpoint made within the cron-jobs were being sent but not appearing in the runtime logs. I also assumed that the requests to api/fetch-transactions were completing based on the messages I returned. However, after your message, another testing method came to mind, and I verified that no requests were being made to the api/fetch-transactions endpoint. I confirmed this by tracking the requests that should have been made by the api/fetch-transactions endpoint to BSC Scan, and I realized that the requests initiated by the cron-jobs were not reaching BSC Scan.

As a result, I sent cron-job requests to the URL of the cron-cache branch I deployed (tokens-ui-nextjs-3yivx8y2k-tahsins-projects-0ae86724.vercel.app) using Postman, and all of them appeared in the runtime logs. In other words, all requests from the cron-jobs to the api/fetch-transactions endpoint were logged and worked correctly this time.

One thing I don’t understand is why this time it gave an error during the build. Should I be concerned about this error?

To fix this error, should I create a server component rather than running cronJobs fetching on Dynamic Functions (server-rendered on demand)? Will it also help to execute revalidate properly?

I read the revalidate and cache documentation, and as I understand it, next.revalidate should fetch and update the data at the specified seconds. But I am doing on-demand revalidation with an API endpoint, which is why it needs a cron-job demand.

I tested it with a 3-minute revalidate time, and after 3 minutes, each /api/cron-jobs request reaches out to the BSC Scan API for new data fetch so cache get clean after revalidate time.

As a result, this scenario helps to fetch all transaction data at once daily with cron-jobs and cache it on the server for a better user experience, even if it doesn’t run at build time?

Thank you very much for the responses. I am unable to change the subject and category of the topic, but if you could update them, I believe it would be more helpful for others. The issue was not with the runtime logs but rather due to a lack of my knowledge…

Also, I deleted the previous comment after understanding next.revalidate. I should have searched for it at the beginning, sorry :smiling_face_with_tear:

Relevant code: cronJobs.ts which is executed by the /api/cron-jobs endpoint:

"use server";
import { revalidatePath } from "next/cache";
import scaffoldConfig from "~~/scaffold.config";

const cronSecret = process.env.CRON_SECRET;
const vercelByPass = process.env.VERCEL_BYPASS;
const testnetAddresses = scaffoldConfig.testnetContractAddressList || [];
const mainnetAddresses = scaffoldConfig.contractAddressList || [];
const baseUrl = process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "http://localhost:3000/";

async function fetchTransactions(contractAddress: string, testnet: boolean) {
  const url = `${baseUrl}/api/fetch-transactions?contractaddress=${contractAddress}&testnet=${testnet}&allTx=true`;
  console.log(`Fetching transactions from URL: ${url}`);

  const headers: Record<string, string> = {
    Authorization: `Bearer ${cronSecret}`,
  };

  if (vercelByPass) {
    headers["x-vercel-protection-bypass"] = vercelByPass;
  }

  const response = await fetch(url, {
    method: "GET",
    headers,
    cache: "no-store",
  });
  console.log(`Response status: ${response.status}`);

  if (!response.ok) {
    console.error(`Failed to fetch transactions: ${response.status} ${response.statusText}`);
    throw new Error(`Failed to fetch transactions for ${contractAddress}`);
  }

  console.log(`Transactions fetched for ${contractAddress}`);
  return `Transactions fetched for ${contractAddress}`;
}

async function delay(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

export async function runCronJobs() {
  console.log("Cron job started");
  revalidatePath("/api/fetch-transactions");
  let resultMessage = "Cron jobs completed with the following results:\n";

  await delay(500);

  for (const address of testnetAddresses) {
    console.log(`Fetching transactions for testnet address: ${address}`);
    try {
      const message = await fetchTransactions(address, true);
      console.log(`Successfully fetched transactions for testnet address: ${address}`);
      resultMessage += `Testnet address ${address}: ${message}\n`;
    } catch (error) {
      if (error instanceof Error) {
        console.error(`Error fetching transactions for testnet address ${address}:`, error);
        resultMessage += `Testnet address ${address}: ${error.message}\n`;
      }
    }
    await delay(500);
  }

  for (const address of mainnetAddresses) {
    console.log(`Fetching transactions for mainnet address: ${address}`);
    try {
      const message = await fetchTransactions(address, false);
      console.log(`Successfully fetched transactions for mainnet address: ${address}`);
      resultMessage += `Mainnet address ${address}: ${message}\n`;
    } catch (error) {
      if (error instanceof Error) {
        console.error(`Error fetching transactions for mainnet address ${address}:`, error);
        resultMessage += `Mainnet address ${address}: ${error.message}\n`;
      }
    }
    await delay(500);
  }
  console.log("Cron job finished");
  return resultMessage;
}

getBscTransactions.ts which is executed by the /api/fetch-transactions endpoint:

"use server";
import { ExtendedTransaction } from "~~/types/utils";

async function fetchData(url: string, revalidateTime?: number): Promise<ExtendedTransaction[]> {
  const response = await fetch(
    url,
    revalidateTime
      ? {
          next: { revalidate: revalidateTime },
        }
      : {
          method: "GET",
          cache: "no-store",
        },
  );
  const data = await response.json();

  if (data.status === "1") {
    return data.result as ExtendedTransaction[];
  } else {
    throw new Error(data.message || "Failed to fetch data");
  }
}
async function delay(ms: number) {
  return new Promise(resolve => setTimeout(resolve, ms));
}
export async function getBscTransactions(
  contractAddress: string,
  testnet: string,
  all: string,
): Promise<ExtendedTransaction[]> {
  if (!contractAddress) {
    throw new Error("Contract address is required");
  }

  const apiKey = process.env.BSC_SCAN_API_KEY;
  const domain = testnet === "true" ? "api-testnet.bscscan.com" : "api.bscscan.com";
  let transactions: ExtendedTransaction[] = [];
  if (all === "true") {
    const maxOffset = 350;
    const revalidateTime = 86200;
    let page = 1;
    const maxRetries = 5;

    while (true) {
      const url = `https://${domain}/api?module=account&action=tokentx&contractaddress=${contractAddress}&page=${page}&offset=${maxOffset}&sort=desc&apikey=${apiKey}`;
      let success = false;
      let retries = 0;
      while (!success && retries < maxRetries) {
        try {
          const fetchedTransactions = await fetchData(url, revalidateTime);
          await delay(200);
          console.log(`Fetched ${fetchedTransactions.length} transactions (page: ${page}, try: ${retries + 1})`);

          if (fetchedTransactions.length === 0) {
            console.log("No transactions found, stopping fetch.");
            return transactions;
          }
          transactions = transactions.concat(fetchedTransactions);
          page++;
          success = true;

          if (fetchedTransactions.length < maxOffset) break;
        } catch (error) {
          retries++;
          console.error(`Error fetching transactions at page ${page}, retry ${retries}:`, error);
          if (error instanceof Error && error.message.includes("No transactions found")) {
            console.log("No transactions found, stopping fetch.");
            return transactions;
          }
        }
      }

      if (!success) {
        console.error(`Failed to fetch transactions after ${maxRetries} retries at page ${page}`);
        break;
      }
    }
  } else {
    const offset = 100;
    const url = `https://${domain}/api?module=account&action=tokentx&contractaddress=${contractAddress}&page=1&offset=${offset}&sort=desc&apikey=${apiKey}`;
    try {
      transactions = await fetchData(url);
    } catch (error) {
      console.error("Error fetching transactions:", error);
    }
  }

  console.log(`Total transactions fetched: ${transactions.length}`);
  return transactions;
}

I’m glad it works now!

One thing I don’t understand is why this time it gave an error during the build. Should I be concerned about this error?

If I remember it correctly, the fetch with no-store might trigger this error when the page itself is not considered dynamic. Adding export const dynamic = 'force-dynamic'; to /api/cron-jobs might resolve that. You usually don’t want to catch this error at build time to make sure it’s forwarded to Next.js to mark the page as dynamic by default.

To fix this error, should I create a server component rather than running cronJobs fetching on Dynamic Functions (server-rendered on demand)? Will it also help to execute revalidate properly?

If I understand it correctly, you want the result of /api/fetch-transactions to be cached, and only revalidated every once in a while. There are multiple ways to achieve this. Maybe instead of a cron job you could use time based revalidation as stated here in your /api/fetch-transactions route. It’ll depend on what kind of behaviour you want exactly, e.g. stale-while-revalidate, or revalidating upfront.

1 Like

Thank you Andy, yes error was triggered by no-store also is triggered by revalidatepath function too.

For now, when I added the export const dynamic = "force-dynamic"; statement to the relevant page, the related error disappeared.

What I don’t understand is that, at the time the error occurred, the api/cron-jobs page was shown as ƒ (Dynamic) server-rendered on demand during the build process, meaning it wasn’t using SSG. After adding force-dynamic, it still shows as ƒ. So, whatever changed in Next.js’s behavior behind the scenes isn’t visible in the build log, which makes it a bit challenging to understand how the framework operates and to deal with errors. This might be something worth exploring further.

Another point is that in the time-based caching mechanism with next.revalidate, there seems to be a subtle nuance in the documentation; the phrase

This will revalidate the Data Cache, which in turn will revalidate the Full Route Cache. Fresh data will be fetched, and components will be re-rendered on the server.*

can be misleading, as it might make it seem like the data will be automatically fetched again after being revalidated—or at least, that’s how I misunderstood it :smiling_face_with_tear:. But in reality, isn’t it true that the data isn’t fetched again unless the fetch function is explicitly called next time…

In my story, I was using a one-day revalidate cache mechanism to quickly display all transaction data on an analytic graph without using any database in the current open-source version. Additionally, I was using a cron job (“refetch every night”) to include the latest data in the cached data for the table. So, it was a bit of a mix between pre-fetch and stale-while-revalidate. But given that this approach isn’t very conventional and there is always a better solution available, I believe it would be more appropriate to use KV to store the data and only fetch and add new data to the KV via a cron job :grin:

So, in conclusion, I now have a better understanding of why Next.js made no-store the default in the latest update, how revalidation or the cache mechanism works, and how Dynamic pages function.

Thanks a lot :pray:.

2 Likes

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.