Payload Plugins
Pluginspayload-revalidate

Reference

Every revalidatePlugin option, default, and export in one place — plus the guarantees the finders and hooks make.

For AI / LLMs: View Markdown

The full surface: plugin options, the import-path map for every export, and the behavioural notes worth knowing. For finder signatures see Writing getters; for the tag vocabulary see The atomic model.

Plugin options

Every option is optional. Zero-config (revalidatePlugin()) gives every collection and global its hooks, and doc tags flow automatically. Declared lists are the one thing worth configuring.

enabledbooleandefault true

Master switch. Set `false` to register no hooks or endpoints at all.

collectionsRecord<string, CollectionRevalidateConfig | false>default {}

Tracking config for YOUR collections, keyed by slug — this plugin registers none of its own, so there's no `slug`/`overrides` here, just the per-collection settings below. Set a slug to `false` to opt the collection out entirely. Omit it and every collection still gets doc tags — just one bare list tag per collection instead of scoped ones.

idFieldstring | falsedefault 'slug' when a slug field exists, else false

The field for the alias doc tag (`posts:my-slug`). Defaults to `'slug'` when the collection has a slug field, otherwise the collection is id-keyed only.

listsRecord<string, string[] | { fields: string[] }>

Declares list scopes — each scope gives a list surface its own tag and names the fields that reorder or filter it (`name: [fields]`, or the longer `name: { fields: [...] }`).

extraTagsstring[]

Fixed tags added to every doc in the collection.

globalsPartial<Record<string, false>>default {}

Opt one of YOUR globals out of revalidation by setting its slug to `false`. Every global is tracked by default.

optionsRevalidateOptions

The plugin's own knobs.

prefixstringdefault ''

Namespaces every emitted tag (e.g. `prefix: "app:"` → `app:posts:my-slug`). Use it to isolate tags when two Payload apps share a cache.

rulesArray<{ on: string; bust: string[]; whenFields?: string[] }>default []

Manual busts for data the field-walk can't see (e.g. content denormalized by an app-level build step). A rule fires when one of its `whenFields` changed, or on any membership event; deletes fire it unconditionally.

observebooleandefault dev only

Force the dependency-map observation and dev warnings on in production. By default they run in development only. It also governs the `/api/revalidate-map` endpoints: they serve nothing but observations, so when `observe` is off they are not registered at all. With `observe: true` in production they additionally require an authenticated Payload user.

idField is per-collection, not top-level. Set it under collections: { posts: { idField: 'uid' } } (or on the collection's custom.revalidate), not as a revalidatePlugin() option. Likewise walk.maxTags (default 64 — caps how many tags the bake-in walk adds to one entry; Next.js allows 128) is a per-read option you pass to a finder / cacheDoc, not a plugin option. Capped reads are flagged in the dev map.

Finder defaults, baked in so you never repeat them: depth: 0 (references stay ids), errors resolve to null, and id-list reads (findIds) are forced to select: {}. Access is not one of them — the finders leave overrideAccess to Payload's own default (true), so a collection with restricted read access reads the same through a finder as through payload.find. Pass overrideAccess: false to scope a read to what an anonymous visitor may see. Override any default per call — except user / req, which the finders refuse (see Writing getters).

Environment variables

None. The plugin reads no environment variables — everything is configured through plugin options.

Endpoints

Two dependency-map routes, governed entirely by observe — dev-only by default. They serve nothing but observations, so with observe: false (the production posture) they are not registered at all. With observe: true forced on in production they additionally require an authenticated Payload user.

RoutePurpose
GET /api/revalidate-mapThe full dependency map as JSON.
POST /api/revalidate-mapBust one tag by hand — body { "tag": "posts:42" }.

These power the /dev/revalidate map — see Troubleshooting.

CLI commands

The plugin registers one bin, so it runs through Payload's own CLI.

CommandWhat
payload revalidate-mapRenders the static dependency map from your config alone — no running site, no observations, so it's the build-time / CI view of what busts what. Prints a text report by default; --json emits the raw inspection, and --out <file> (-o) writes it to a file instead of stdout.

Exports

Two import entry points, plus the finders and primitives you get back from the factory.

Package root@pro-laico/payload-revalidate

ExportPurpose
revalidatePluginThe plugin. Add it last in plugins: [].
tagsFortagsFor(payload) builds prefix-correct raw tags for the rare hand-spelled cacheTag need.
readRevalidateMarkerreadRevalidateMarker(config) returns the typed config.custom.payloadRevalidate — the resolved prefix, observe, lists, extraTags, rules, and the map endpointPath (non-null only while observing).
getInspectionThe live dependency map for this process (observed reads + graph), or null when the plugin isn't active. What GET /api/revalidate-map and /dev/revalidate serve.
buildStaticInspection · renderRevalidateMapBuild the static map from a config (MapConfigSource) and render it to the text report — the machinery behind payload revalidate-map, for custom CI checks or map UIs.

Cache helpers@pro-laico/payload-revalidate/cache

ExportPurpose
createCacheHelpersSeed once with your live Payload handle; returns the finders, primitives, and manual busters below.

Factory returns — destructured from createCacheHelpers(db), not imported

ReturnPurpose
findDocByIDOne doc by id → its id-keyed entry. The atomic unit.
findDocOne doc by query, with alias (as) and draft tagging.
findIdsAn id-list plus pagination meta, no second query.
findGlobalA global.
cacheDoc · cacheIds · cacheGlobalThe low-level primitives a finder wraps, for getters the finders can't express.
revalidateDocBust one doc's tags. Lane-aware (published + :draft) and prefix-aware.
revalidateListBust a collection's bare list tag plus every declared scope.
revalidateGlobalBust a global's tags.
revalidateAllBust the all tag — every tagged entry.

Notes

  • Add the plugin last in plugins: [] — it can only hook collections that exist when it runs (a boot-time warning names anything registered after it).
  • Failure paths are loud in every environment, once per process: cacheTag failing (entry materializing untagged), the config being unreachable (bake-in walk skipped), and revalidateTag no-oping outside a request scope all console.error/warn — a production jobs runner silently not revalidating is the one thing this plugin refuses to be quiet about.
  • The map endpoints are registered only while observe is on, so the production default leaves them off the config entirely. With observe: true forced on in production, they additionally require an authenticated Payload user.
  • The cache helpers never resolve Payload or your config themselves — no globalThis stashes, no @payload-config alias tricks, no transpilePackages requirement. The handle you seed into createCacheHelpers is the session that runs and tags every read.
  • A draft save over a published doc is indistinguishable from an unpublish in the hook signature, so both lanes bust — a harmless over-bust that keeps unpublish correct.
  • Collections without a slug field get no alias tag — id-keyed reads only.
  • The bake-in walk is capped (walk.maxTags, default 64; Next allows 128 tags/entry); capped reads are flagged in the map.
  • Bare posts list tags bust on membership only — an unscoped findIds read that depends on sort/filter fields should declare a scope instead.

Next

On this page