Indexing 100,000 nodes one at a time, on cron, the same way you'd index 100, is a recipe for a cron run that never finishes within its time budget. Search API's own architecture already batches indexing — this lesson is about tuning the knobs that control how much work happens per batch, and where the real bottleneck usually is.
What you'll learn in this lesson
- The cron indexing limit, and why bigger isn't automatically better
- Why indexing performance is usually a "how much per item" problem, not a "how many items" one
- Track changes so cron doesn't have to check every item every run
The cron batch size setting
// /admin/config/search/search-api/index/{index}/edit — "Cron limit"
// Or programmatically:
$index = \Drupal\search_api\Entity\Index::load('default_index');
$index->setOption('cron_limit', 50);
$index->save();
This caps how many items get indexed per cron run, not per site — same principle as the Batch API's chunking from the Cron and Queue Optimization section. Too low, and a large content backlog takes many cron cycles to fully index; too high, and one cron run risks exceeding your PHP execution time limit partway through.
cron_limit to index "more, faster," profile what a single item's indexing actually costs — the fix is often reducing what gets computed per item, not processing more items per run.Track changes, don't re-check everything
Search API's tracker system already knows which items are new, changed, or already indexed — it doesn't re-index unchanged content on every cron run by default. If you've written custom code that forces re-indexing more broadly than necessary (a batch operation that calls trackItemsUpdated() too liberally, say), you're paying indexing cost for content that never actually changed.
// Correct: only mark items that genuinely changed.
\Drupal::getContainer()->get('search_api.index_task_manager');
$index->trackItemsUpdated('entity:node', [$node->id()]);
// Not: forcing a full re-track of every item in the index on unrelated saves.
Quick check: raising
cron_limitfrom 50 to 500 made indexing take noticeably longer per cron run without meaningfully reducing the total backlog over several days. What's more likely: the limit itself is wrong, or per-item indexing cost is the real problem? If you said per-item cost, you've understood why this lesson emphasizes profiling before tuning the batch size blindly.
Key takeaways
cron_limitcontrols items indexed per cron run — size it against your PHP execution time limit, not arbitrarily high.- Per-item indexing cost usually matters more than item count — profile what a single item's indexing actually does before raising the limit.
- Search API's tracker already avoids re-indexing unchanged content — don't force broader re-tracking than a change actually warrants.
Coming up next
Indexing performance affects how fresh your search results are. Next, query-side caching — how fast search actually answers a visitor's query.