VCL error caching

i have some vcl that in vcl_fetch based on a response status from the backend triggers an vcl_error command that moves to vcl_error that will produce a synthetic response with an empty response body that just produces a redirect to a different host with a 301 moved permanently status. something like this.
if (obj.status == some status) {
set obj.status = 301;
set obj.response = “Moved Permanently”;
set obj.http.Location = “https://” req.url “?(some query param)”;
synthetic {“”};
return (deliver);

for some reason im seeing that response of the 301 with the location header of the url being cached for 2 minutes with the query param but only on edge pops, if i hit the shield server directly it does not trigger a cache hit. this service is shielded. i can see its being cached via the Age response header back to the client. i think there is a default 2 minute cache being set by fastly based on some condition. i see the age of the response header build up to 120 before being reset.

ive tried in vcl fetch setting beresp.cacheable to false before triggering the vcl_error subroutine command with a specific status, but it does not seem to work. is there a way to avoid having this flow getting cached? i think im missing something. id like it to avoid being cached. Thank you!


Thanks for reaching out! Could you please provide a full URL I can use to test?

its just a test service right now. more looking for general idea about the 2 min cache.

It is difficult to know for certain without the test URL, because to my knowledge we don’t set a 2 minute TTL by default. It’s typical to see a 3600 second TTL on a new service configured in the default state.

The reason for the difference between the Edge and Shield cache timing is also not clear without the test URL.

It may be preferable to submit an email to from your Fastly user email address. That way we can open a ticket and exchange information privately.

If this works for you, then you can mention my name (Donovan) in the email, and the ticket will be routed to me directly.

Correction: Running this Fiddle, we can see in the vcl_fetch output down the right side that the default TTL is 120 seconds (2 minutes) as you described.

In this reference, it can be seen that the default cache TTL is 2 min if no Surrogate-Control, Cache-Control: s-maxage or max-age, or no Expires header exists.

I did some additional testing on a blank Fiddle and saw the default TTL is 60 min. This is because Fiddle uses similar code to our VCL boilerplate, which sets beresp.ttl to 3600 seconds at the bottom of vcl_fetch.

Therefore, the key is that if vcl_fetch is exited prematurely (such as in the case of calling vcl_error), then there is no TTL set at all, and we default to the 2 minute TTL mentioned above.

is there a way to avoid having this flow getting cached?

Yes, could you try:

set beresp.ttl = 0s;

oh nice i think i tired that before i made the post. didnt work i think.
but ill try it again.

set var.response_url = “https://” req.url;
set beresp.ttl = 0s;
error 750 var.response_url;

just before i call vcl error i set beresp.ttl = 0s; i also tried beresp.cacheable = false as well.