#How to cache individual external requests made from the server from an on-demand rendered page

7 messages · Page 1 of 1 (latest)

stray stream
#

Hi.

I'm implementing an on-demand SSR route with dynamic params like:

  • /food/[type]/[variation]

I need to validate params against an external API, with these constraints:

  • External API must be called server-side only (never from client/browser)
  • Validation order must be:
    1. validate [type]
    2. then validate variation (because variation options depend on food type)

Desired behaviour:

  • Fetch and cache the full valid food types list once (e.g. cache key: food-types).
  • For each request, validate type from that cached dataset first.
  • Only if valid, proceed to "variation" validation (which may use a second cache key like food-types:{type}).
  • Avoid repeated upstream API calls for random invalid route attempts (such as /food/apple/asdasd)
  • Be able to invalidate these cache entries from an API endpoint (e.g. /api/revalidate) when upstream data changes.

Main uncertainty:
My understanding is that default Astro/page caching is only tied to rendered pages, not to internal upstream fetches; so without explicit data caching, requests to new dynamic URLs (including invalid params) would still execute server logic and potentially re-hit the external API. Is that correct?

Questions

  1. What is the recommended Astro pattern for shared server-side data caching across dynamic SSR requests?
  2. Are there Astro-native APIs/features that help enforce this validation/caching flow cleanly, or is my only option to look at other options such as Redis etc?

Thanks!

reef mangoBOT
#

Hi @stray stream. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Great questions! Let me address your understanding and then answer each question based on what the Astro docs cover.

Your Core Understanding

You are correct. Astro's route/page caching (experimental or otherwise) is tied to caching the rendered response of a page, not individual upstream data fetches made within that page. The experimental route caching API (Astro.cache) controls HTTP-level response caching for the rendered page, not a general-purpose server-side data cache for arbitrary fetch calls. [Experimental route caching]

This means that without explicit data caching, every request to /food/apple/asdasd (even with an invalid param) would still execute your server logic and potentially hit the external API before the page response is cached.


Question 1: Recommended Astro Pattern for Shared Server-Side Data Caching

The Astro docs do not describe a native, general-purpose server-side data cache (e.g., a shared in-memory store for upstream fetch results across requests). The caching primitives Astro provides are:

  1. Experimental Route Caching (Astro.cache / context.cache): Caches the full rendered response of a page or endpoint, not individual data fetches. It supports maxAge, swr, tags, and invalidation. [Using route caching]
#
  1. Live Content Collections with Cache Hints: If you use Astro's live content loaders, they can return cacheHint objects (with tags and lastModified) that you can pass to Astro.cache.set(). This integrates loader-level hints with route-level response caching — but again, this caches the response, not the raw data fetch. [Cache hints]

  2. Sessions: Astro sessions store data server-side across requests, but they are user-scoped (per-session), not shared across all users/requests. [Sessions]

For your use case (a shared, cross-request server-side data cache for upstream API results), the knowledge sources do not describe a native Astro API for this. An external solution like Redis (via Astro's session driver support or directly) would be the appropriate tool.


Question 2: Astro-Native APIs for Your Validation/Caching Flow

Here's what Astro does offer that's relevant:

Route-Level Response Caching (Experimental)

You can cache the rendered response of /food/[type]/[variation] using tags, so that valid pages are cached and can be invalidated later:

// src/pages/food/[type]/[variation].astro
---
export const prerender = false;

// Your validation logic here (external API calls)
const isValidType = await validateType(Astro.params.type);
if (!isValidType) return Astro.redirect('/404');

const isValidVariation = await validateVariation(Astro.params.type, Astro.params.variation);
if (!isValidVariation) return Astro.redirect('/404');

// Cache the valid response with tags for targeted invalidation
Astro.cache.set({
  maxAge: 3600,
  swr: 60,
  tags: ['food-types', `food-types:${Astro.params.type}`],
});
---
#

[Setting cache options]

Tag-Based Invalidation from an API Endpoint

You can invalidate cached responses by tag from /api/revalidate:

// src/pages/api/revalidate.ts
export async function POST(context) {
  await context.cache.invalidate({ tags: ['food-types'] });
  // Or invalidate a specific type:
  // await context.cache.invalidate({ tags: ['food-types:apple'] });
  return Response.json({ purged: true });
}

[Invalidation]

What This Does NOT Solve

  • Invalid param requests will still hit your external API on the first request (before a cached response exists). Route caching only prevents re-rendering after a successful cached response is stored. For invalid params, no response is cached, so every invalid request re-executes your validation logic.
  • There is no Astro-native API described in the docs for caching the result of an upstream fetch (e.g., the list of valid food types) in a shared server-side store across all requests.

Summary

Need Astro-Native Solution Notes
Cache rendered page responses ✅ Experimental route caching Supports tags, SWR, invalidation
Invalidate by tag from API cache.invalidate() Tag or path based
Shared server-side data cache (upstream fetches) ❌ Not described in docs Use Redis or similar externally
Per-user server-side storage ✅ Sessions Not shared across users
#

For your specific requirement of caching upstream API validation data (food types list) shared across all requests, the knowledge sources do not describe a native Astro solution — you would need an external caching layer such as Redis.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@stray stream Kapa.ai is still learning and improving, please let me know how I did by reacting below.