Skip to content

Preload & Caching

Normative language (MUST/SHOULD/MAY) follows the conventions defined in Conformance Language.

This document defines the optional preload field on route level. It signals that a route returns a static or slow-changing dataset and that the runtime MAY cache the response locally.


Some API endpoints return complete, rarely changing datasets (e.g. all hospitals in Germany, all memorial stones in Berlin). Fetching these on every call wastes bandwidth and time. The preload field lets schema authors declare caching intent so the CLI and other runtimes can cache responses transparently.


preload is an optional object on route level, alongside method, path, description, parameters, output, and tests.

routes: {
getLocations: {
method: 'GET',
path: '/locations.json',
description: 'All hospital locations in Germany',
parameters: [],
preload: {
enabled: true,
ttl: 604800,
description: 'All hospital locations in Germany (~760KB)'
},
output: { /* ... */ },
tests: [ /* ... */ ]
}
}
FieldTypeRequiredDescription
enabledbooleanYesWhether caching is allowed for this route. Must be true to activate caching.
ttlnumberYesCache time-to-live in seconds. Must be a positive integer.
descriptionstringNoHuman-readable note shown on cache hit (e.g. dataset size, update frequency).
  • enabled: true signals that the route’s response is safe to cache. The runtime decides whether to actually cache (caching is always optional).
  • enabled: false explicitly disables caching even if present. Equivalent to omitting preload entirely.
  • ttl defines the maximum age of a cached response in seconds before it must be re-fetched. Common values:
TTLDurationUse Case
36001 hourFrequently updated data
864001 dayDaily snapshots
6048001 weekWeekly releases, semi-static data
259200030 daysStatic reference data

These rules extend the existing validation rule set from 09-validation-rules.md:

CodeSeverityRule
VAL060errorIf preload is present, it must be a plain object.
VAL061errorpreload.enabled must be a boolean.
VAL062errorpreload.ttl must be a positive integer (> 0).
VAL063warningpreload.description if present MUST be a string.
VAL064infoRoutes with preload.enabled: true and no parameters are ideal cache candidates.
VAL065warningRoutes with preload.enabled: true and required parameters SHOULD document caching behavior — the cache key MUST include parameter values.

When a route has parameters, the cache key MUST include the parameter values to avoid serving stale data for different inputs. The recommended cache key format is:

{namespace}/{routeName}/{paramHash}.json

Where paramHash is a deterministic hash of the sorted, JSON-serialized user parameters.

For routes with no parameters (or only optional parameters that were omitted), the cache key simplifies to:

{namespace}/{routeName}.json

The recommended cache directory is ~/.flowmcp/cache/. Each cached response is stored as a JSON file with metadata:

{
"meta": {
"fetchedAt": "2026-02-17T12:00:00.000Z",
"expiresAt": "2026-02-24T12:00:00.000Z",
"ttl": 604800,
"size": 760123,
"paramHash": null
},
"data": { }
}

No

Yes

No

Yes

No

Yes

flowmcp call tool-name

preload.enabled?

Normal fetch

Cache file exists?

Fetch + store in cache

Cache expired?

Return cached response

Return fresh response

Runtimes SHOULD support these override mechanisms:

FlagBehavior
--no-cacheSkip cache entirely, always fetch fresh
--refreshFetch fresh and update cache

Runtimes SHOULD provide cache management:

CommandDescription
cache statusList all cached responses with size, age, expiry
cache clearRemove all cached responses
cache clear {namespace}Remove cached responses for a specific namespace
EventMessage
Cache hitCached (fetched: {date}, expires: {date})
Cache missFetching fresh data...Cached for {ttl human}
Cache expiredCache expired, refreshing...
Force refreshRefreshing cache...

Use preload when:

  • The endpoint returns a complete, static or slow-changing dataset
  • The response is larger than ~10KB
  • The data doesn’t change based on time-of-day or real-time events
  • Multiple calls with the same parameters return identical results

Do not use preload when:

  • The data changes frequently (live prices, real-time feeds)
  • The response depends on authentication state
  • The endpoint has rate limits that make caching counterproductive (use rate limiting instead)

Yes

No

Yes

No

Yes

No

How often does this data change?

Daily or more?

ttl: 3600-86400

Weekly?

ttl: 604800

Monthly or less?

ttl: 2592000

Don't use preload


Handlers (preRequest, postRequest) still execute on cached data. The cache stores the raw API response before postRequest transformation. This ensures handler logic always runs on the most appropriate data format.

Alternative (simpler): Cache the final transformed response after postRequest. This avoids re-running handlers on every cache hit but requires cache invalidation when handler logic changes.

Runtimes SHOULD document which approach they use.

Route tests (10-route-tests.md) always bypass the cache to ensure they test the live API. The --no-cache flag is implied during test execution.

The output schema (04-output-schema.md) describes the response shape regardless of whether the response comes from cache or a live fetch. Caching does not affect the output contract.