Sync Contentful entries to Algolia every 15 minutes

Every 15 minutes, freshly published Contentful entries are pushed into your Algolia search index so your site search never drifts from the CMS.

Deterministic Code
ContentfulAlgoliaMarketingOperationsData Sync
PromptCreate

Every 15 minutes, sync recently published Contentful entries into an Algolia search index so our public site search stays in step with the CMS. This is a deterministic, code-style workflow triggered by a cron schedule running every 15 minutes.

Configuration (all editable in one place at the top of the workflow):

1) Contentful space id, environment id (default "master"), and Delivery API access token. 2) Algolia application id, admin API key, and target index name. 3) A list of content types to index — default to article, product, and landingPage — and for each content type, three arrays: searchableFields (mapped into Algolia's searchable attributes), filterableFields (mapped into attributesForFaceting), and displayFields (kept on the record but not searchable). 4) A path in the workflow's key/value store where the last successful run's high-water mark is persisted.

On each run:

Step 1 — Read the last successful high-water mark (sys.updatedAt) from the workflow store. If none exists yet (first run), default to 24 hours ago so we backfill a reasonable window without hammering the API.

Step 2 — For each configured content type, call Contentful "CDA - Get Published Entries" with query params content_type=<type>, sys.updatedAt[gt]=<lastRunIso>, order=sys.updatedAt, and limit=200. Page through results using skip/limit until skip + items.length >= total. Collect every returned entry.

Step 3 — Build the Algolia batch. For each Contentful entry, produce a flat record: objectID = the Contentful sys.id; contentType = sys.contentType.sys.id; updatedAt = sys.updatedAt; locale = sys.locale (or the space's default locale). Then copy fields listed in the content type's searchableFields, filterableFields, and displayFields into the record, resolving localized values against the default locale. Reference fields should be flattened to their linked entry's id and (where available) title/slug — do not recurse. Wrap each record in an Algolia batch action of type "addObject" (add or replace by objectID).

Step 4 — Handle deletions and unpublishes. The Content Delivery API only returns published entries, so anything previously in the index but no longer present needs to be removed. Two approaches are acceptable — pick whichever fits the space best: (a) maintain a persisted set of known objectIDs per content type in the workflow store, diff against the current published set for the content types we just fetched (using a full paged fetch without the updatedAt filter on the same 15-minute cadence would be expensive, so instead diff only the content types where we saw new activity); or (b) subscribe to sync deletions via the Contentful sync API when available. For MVP, use approach (a): for each content type touched this run, list currently-published objectIDs, compare with the stored set, and emit an Algolia "deleteObject" action for every objectID missing from the current set. Persist the updated known-id set at the end of the run.

Step 5 — Push the combined add/replace + delete actions to Algolia in a single call to "Batch Write (single index)" against the target index. If the batch is larger than 1,000 operations (Algolia's per-request cap in practice), chunk it into requests of 1,000 and issue them sequentially, keeping every taskID.

Step 6 — Record the returned taskID(s) in the workflow logs and add a log line noting that Algolia writes are asynchronous and reads will settle within seconds. Do not poll the task endpoint — the 15-minute cadence provides plenty of settling time before the next run.

Step 7 — On success, persist the new high-water mark: the maximum sys.updatedAt across all entries fetched this run. If nothing was fetched, leave the previous high-water mark in place so the next run re-attempts the same window.

Error handling: on a Contentful 429, back off using the X-Contentful-RateLimit-Reset header before retrying. On an Algolia 5xx or network failure, retry the batch against the numbered fallback hosts (<app>-1.algolianet.com, -2, -3). On any 4xx from Algolia other than 429, fail the run and leave the high-water mark unchanged so the next run picks the same window back up. Log the count of adds, replaces, and deletes emitted per run.

One-time setup at first run: configure the Algolia index's searchableAttributes and attributesForFaceting from the union of the configured searchableFields and filterableFields across all content types. This lets the same index serve multiple content types with sensible defaults; leave it alone on subsequent runs unless the configuration changes.

Additional information

What does this prompt do?
  • Every 15 minutes we check Contentful for entries that have been published or updated since the last run.
  • Each entry is flattened into a search-friendly record and pushed into your Algolia index, keyed on its Contentful id so updates cleanly replace the old version.
  • Anything unpublished or deleted in Contentful gets removed from the Algolia index in the same batch, so your site search never shows dead content.
  • You choose which content types to index (articles, products, landing pages) and, for each one, which fields are searchable, filterable, or just displayed.
What do I need to use this?
  • A Contentful space with a Delivery API access token that can read published entries.
  • An Algolia account with an Admin API key and a target search index.
  • A short list of the Contentful content types you want to appear in site search, and which fields on each type should power search, filters, and result cards.
How can I customize it?
  • Change the schedule — 15 minutes is a good default, but you can run it every 5 minutes for fresher search or hourly to reduce API load.
  • Add or remove content types (articles, products, landing pages, authors, categories) and pick per-type which fields become searchable, filterable, or just displayed.
  • Point at a staging Algolia index first, then flip to production once the mapping looks right.

Frequently asked questions

How fast will changes in Contentful show up in site search?
On the default 15-minute cadence, worst case is about 15 minutes plus a few seconds for Algolia to settle the batch. Speed it up by shortening the schedule; the workflow only sends entries that actually changed, so shorter intervals stay cheap.
What happens when I unpublish or delete an entry in Contentful?
It is removed from the Algolia index on the next run, in the same batch as the new and updated entries. Nothing goes stale.
Can I index more than one content type into a single Algolia index?
Yes. Each record carries its content type as a field, so you can facet and filter search results by content type inside a unified index.
Will this cost a lot in Algolia operations?
No. Only entries that changed since the last run are pushed, and they are batched into as few requests as possible. Most 15-minute runs will send a handful of operations or none at all.
Does this work with Contentful's localization?
Yes. Each run resolves localized fields against the space's default locale by default. You can extend the mapping to emit one record per locale if you run localized search.

Stop letting site search fall behind your CMS.

Wire Contentful to Algolia once and forget it — every 15 minutes, new and changed entries land in search and stale ones disappear.