Next.js Discord

Discord Forum

Confusing about vercel edge cache behavior

Answered
bubble 03 posted this in #help-forum
Open in Discord
Hi 👋 , I am confused about vercel edge cache. I am making request to API route which is edge runtime and it fetches the remote audio segment file and I set CDN cache in API route. Below is my API route.

export const runtime = "edge";
import { type NextRequest, NextResponse } from "next/server";

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const query: string | null = searchParams.get("with");
  if (query) {
    console.log(query);
    const fetchData = await fetch(query, {
      priority: "high",
      headers: {
        "Cache-Control": "public, max-age=31536000, immutable",
      },
    });
    const response = new NextResponse(await fetchData.arrayBuffer(), {
      status: fetchData.status,
      headers: fetchData.headers,
    });
    response.headers.set(
      "Cache-Control",
      "public,max-age=31536000,smax-age=31536000"
    );
    response.headers.set(
      "CDN-Cache-Control",
      "public,max-age=360000,smax-age=360000"
    );
    return response 
  }
  return NextResponse.json(
    { error: "Query parameter 'with' is missing" },
    { status: 400 }
  );
}


And the response after first request is included

Cf-cache-status: Dynamic 
x-vervel-cache : HIT


My question is that is there any way to change cloudflare cache status dynamic to miss or hit as dynamic means it doesn't consider to be cache although my audio segment file are static and even vercel can cache it.

I am sorry if I misunderstood something in this content. Please answer me.
Answered by B33fb0n3
Thanks for send your issue again. When you want to stream audio, you need a provider for that, that you can use to stream your audio files. And no, vercel cdn is not the correct one. And no, it's not something that you can make on your own as you can see on cloudflare [(they havent this integrated yet)](https://community.cloudflare.com/t/streaming-audio-not-video-on-cloudflare/526970).

So get a provider that can stream audio. Keep in mind: I am talking about streaming not just serving files
View full answer

38 Replies

Pls answer 😭
Hello?
@bubble 03 Hi 👋 , I am confused about vercel edge cache. I am making request to API route which is edge runtime and it fetches the remote audio segment file and I set CDN cache in API route. Below is my API route. export const runtime = "edge"; import { type NextRequest, NextResponse } from "next/server"; export async function GET(request: NextRequest) { const searchParams = request.nextUrl.searchParams; const query: string | null = searchParams.get("with"); if (query) { console.log(query); const fetchData = await fetch(query, { priority: "high", headers: { "Cache-Control": "public, max-age=31536000, immutable", }, }); const response = new NextResponse(await fetchData.arrayBuffer(), { status: fetchData.status, headers: fetchData.headers, }); response.headers.set( "Cache-Control", "public,max-age=31536000,smax-age=31536000" ); response.headers.set( "CDN-Cache-Control", "public,max-age=360000,smax-age=360000" ); return response } return NextResponse.json( { error: "Query parameter 'with' is missing" }, { status: 400 } ); } And the response after first request is included Cf-cache-status: Dynamic x-vervel-cache : HIT My question is that is there any way to change cloudflare cache status dynamic to miss or hit as dynamic means it doesn't consider to be cache although my audio segment file are static and even vercel can cache it. I am sorry if I misunderstood something in this content. Please answer me.
correct me if I am wrong: you want to load an audio file inside you app?

If so, show where you need that and how you consuming the endpoint. Also show where this file will be used.

If not, explain more what you want to do
@B33fb0n3 correct me if I am wrong: you want to load an audio file inside you app? If so, show where you need that and how you consuming the endpoint. Also show where this file will be used. If not, explain more what you want to do
Hi thanks for the response.

My audio files are remote file in s3 bucket not in project public folder and I am using url of these remote file to access them and fetch them.

Where confused come from is that after fetch I have response in browser and it has two cache indicator. One is cf-cache-status: Dynamic
And one is x-vervel-cache: HIT or Miss.

I don't know how vercel can cache hit even though cf-cache-status is dynamic everytime I request data.

Is there any way to make cf-cache-status: HIT or Miss not dynamic?
@bubble 03 Hi thanks for the response. My audio files are remote file in s3 bucket not in project public folder and I am using url of these remote file to access them and fetch them. Where confused come from is that after fetch I have response in browser and it has two cache indicator. One is cf-cache-status: Dynamic And one is x-vervel-cache: HIT or Miss. I don't know how vercel can cache hit even though cf-cache-status is dynamic everytime I request data. Is there any way to make cf-cache-status: HIT or Miss not dynamic?
the cf-cache-status will never be HIT or MISS. It will either be DYNAMIC or STATIC. The HIT or MISS from vercel is the cache for the route handler. I guess you are using next14 so GET requests will be cached by default.

Can you do this:
show where you need that and how you consuming the endpoint. Also show where this file will be used.
@B33fb0n3 the cf-cache-status will never be HIT or MISS. It will either be DYNAMIC or STATIC. The HIT or MISS from vercel is the cache for the route handler. I guess you are using next14 so GET requests will be cached by default. Can you do this: > show where you need that and how you consuming the endpoint. Also show where this file will be used.
import React, { RefObject } from "react";
export const fetchSegement = (
  url: string,
  sourceBuffer: RefObject<SourceBuffer | null>,
  mediaSource: RefObject<MediaSource | null>,
  segNum: number | undefined = undefined,
  abortController: AbortController | null //need to get the data from other side ,so not use current
) => {
  const fetchOptions: RequestInit = {
    signal: abortController?.signal,
    priority: "high",
    headers: {
      "Cache-Control": "public, max-age=31536000, immutable",
    },
  };

  const outputUrl = segNum ? url.replace("init.mp4", seg-${segNum}.m4s) : url;
  fetch(/api/sound?with=${outputUrl}?static=true, fetchOptions)
    .then((response) => {
      if (!response.ok) {
        throw new Error(failed to fetch the song segements sege-${segNum});
      }
      return response.arrayBuffer();
    })
    .then((buf) => {
      if (
        sourceBuffer.current?.buffered &&
        !sourceBuffer.current.updating &&
        mediaSource.current?.readyState
      ) {
        // console.log(segNum, "it got buffend");
        sourceBuffer.current!.appendBuffer(buf);
      }
    })

    .catch((err) => {
      if (err.name === "AbortError") {
        console.log(the song segements sege-${segNum} fetching is aborted);
      } else {
        console.error(Error fetching segements sege-${segNum}, err);
      }
    });
};

What I am doing is that I use vercel edge CDN to fetch audio remote file as proxy,
@B33fb0n3 the cf-cache-status will never be HIT or MISS. It will either be DYNAMIC or STATIC. The HIT or MISS from vercel is the cache for the route handler. I guess you are using next14 so GET requests will be cached by default. Can you do this: > show where you need that and how you consuming the endpoint. Also show where this file will be used.
export const runtime = "edge";
import { type NextRequest, NextResponse } from "next/server";

export async function GET(request: NextRequest) {
  const searchParams = request.nextUrl.searchParams;
  const query: string | null = searchParams.get("with");
  if (query) {
    console.log(query);
    const fetchData = await fetch(query, {
      priority: "high",
      headers: {
        "Cache-Control": "public, max-age=31536000, immutable",
      },
    });
    const response = new NextResponse(await fetchData.arrayBuffer(), {
      status: fetchData.status,
      headers: fetchData.headers,
    });
    response.headers.set(
      "Cache-Control",
      "public,max-age=31536000,smax-age=31536000"
    );
    response.headers.set(
      "CDN-Cache-Control",
      "public,max-age=360000,smax-age=360000"
    );
    return response 
  }
  return NextResponse.json(
    { error: "Query parameter 'with' is missing" },
    { status: 400 }
  );
}

This is my API / route
@B33fb0n3 where do you consume that buffer?
Hi thanks for the reply.
It is in the code.
sourceBuffer.current!.append buffer(buf : response Buffer);
If you github project is public, you can also directly share your project as well. That would save a lot of time and I can solve your issue while you are not beeing on discord
@bubble 03 Hi thank you for your help. I will make a new repo for this because my main account is suspended rn. https://github.com/aungchanpyae3/bubble---Copy
Thanks for sharing the repo. Just to be on the same page, I created a runnable version of it: https://codesandbox.io/p/github/aungchanpyae3/bubble---Copy/csb-5ctsk8/draft/brave-frost

If you change your source code inside the repo, this version will also update
When I see this correctly, you just want to play an audio. And of course you also want to be able to control it (pausing, next, ...) correct?
@B33fb0n3 When I see this correctly, you just want to play an audio. And of course you also want to be able to control it (pausing, next, ...) correct?
Hi I really appreciate your help.
For your information,audio function controls are already done.

https://vercel.com/docs/edge-network/caching

My confuses is when fetching audio file through API route to cache file in vercel cdn , two things are caught my eyes in network response,
One is Cf-cache-status: dynamic(everytime I request),
Second is x-vercl-cache : HIT or Miss.
How vercel cache can hit happens although cf is dynamic?
Is this possible to make Cf-cache-status: HIT MISS?
I tested your app and saw that many things already integrated
Yeah
Like play pause
I use media source extension to play segment file
Thanks for confirming it. Can I ask you, why you are not using the native audio html element? https://www.w3schools.com/html/html5_audio.asp

And that with a CDN?
Because it is not efficient for music streaming. Native audio element load all data even when not needed
With MSE , It can serve audio part where it is needed
@bubble 03 Because it is not efficient for music streaming. Native audio element load all data even when not needed
oh the audio element itself just plays the loaded audio and requests it from the CDN. When and how much content will be loaded depends on your CDN. Have you checked this?
.
I mean it will only request new segment file when some buffer limit is reached
When user seek to end bar , it will only request needed part , end parts
@bubble 03 I mean it will only request new segment file when some buffer limit is reached
depending on your CDN configuration you will then load only a part of the content. Attached you can see an example of a video for what I am talking about. As you can see the content length is very small. Because I am at 0:00 and it will only be loaded until 0:02 or 0:03 or ... And when I reach this point for example 0:02 the next part will be loaded.

When I seek thought the bar, the new content will also load fast (because it's small) and load only a part of it. Imagine I jump to 2:43 then only the next part is loaded. For example to 2:46 and so on. The same applies for audio
Ok may be my English is not good and clear in previous conversation.
But I have already implement this behavior on my AudioPlayer.

const bufferThreshold = 20(or 5 to reduce fetch aggressive);
bufferThreshold > remainingBuffer
And I only load segment file when it is greater than this.
Pls can you check why Cf-cache-status dynamic
@bubble 03 Pls can you check why Cf-cache-status dynamic
Thanks for send your issue again. When you want to stream audio, you need a provider for that, that you can use to stream your audio files. And no, vercel cdn is not the correct one. And no, it's not something that you can make on your own as you can see on cloudflare [(they havent this integrated yet)](https://community.cloudflare.com/t/streaming-audio-not-video-on-cloudflare/526970).

So get a provider that can stream audio. Keep in mind: I am talking about streaming not just serving files
Answer
I can see now and yeah this is my misunderstanding.
Thanks for your help and time mate.
@B33fb0n3 Is your issue solved like that?
Yeah I need to think and research again to my code structure.
@bubble 03 Yeah I need to think and research again to my code structure.
yea, get a CDN that supports audio stream (not video streaming and not just file serving). Especially audio streaming and then you safe yourself a lot of time