ILM Rollover vs Curator-Based Rotation
For most of a decade, the standard way to keep an Elasticsearch time-series pipeline from filling its disks was elasticsearch-curator: an external Python tool, invoked from cron, that issued a scripted sequence of delete, rollover, forcemerge, and snapshot calls against the API on a fixed clock. Index Lifecycle Management (ILM) replaced that model with a declarative state machine that lives inside the deployment and reconciles each managed index against a policy. Teams migrating off Curator cron scripts need a precise answer to two questions: which Curator actions map one-to-one onto ILM, and where the two models diverge in ways that change operational behaviour. This page draws that map for a syslog rotation pipeline, weighing the trade-offs fairly rather than pitching one tool as universally superior.
The comparison only makes sense against the architecture ILM plugs into. Curator treats the deployment as an opaque endpoint it fires commands at; ILM treats it as a set of data tiers whose allocation state it is continuously aware of. That difference — external imperative scripting versus internal declarative reconciliation — is the root of almost every behavioural gap discussed below, and it is grounded in the Index Lifecycle Management (ILM) control plane. What follows assumes you have an existing rotation to migrate and want to understand exactly what you gain, what you give up, and what stays the same.
Prerequisites
Architecture: External Cron vs Internal Reconciliation
Curator and ILM produce overlapping outcomes — both roll over, force-merge, and delete indices — but they arrive there through opposite mechanics. Curator is a batch program: cron wakes it on a schedule, it evaluates a filter chain against the current index list, issues the matching imperative API calls, and exits. Between invocations nothing watches the deployment. If a delete call lands while a shard is mid-relocation, or fires a rollover into a tier that is over its disk watermark, Curator has no way to know — it has already returned control to cron. ILM, by contrast, runs as a coordinator on the elected master, polling every indices.lifecycle.poll_interval (default 10m) and advancing each managed index one step at a time, only when the deployment’s allocation state allows it.
The consequence is that the two tools fail differently. A Curator run that hits a transient error typically aborts the action and waits for the next cron tick, potentially skipping a rotation entirely; nothing records that the index is now behind. ILM records the failure as an ERROR step on the specific index, holds it there without touching its neighbours, and retries the same step on the next poll once the underlying condition clears. Neither is strictly better in the abstract, but ILM’s per-index, retry-until-ready model is far easier to reason about at fleet scale, because the state of every index is queryable at any instant through GET <index>/_ilm/explain rather than reconstructable only from cron logs.
Curator also has no concept of a phase clock tied to the rollover event. It filters on creation_date or name, computing age from when an index was created. ILM’s min_age in warm, cold, and delete phases is measured from the moment the index rolled over, not when it was created. That single semantic shift is the most common source of surprise during a migration: a retention window that read “delete indices older than 90 days” under Curator is not automatically the same 90-day window under ILM, because the clock now starts later.
Capability Comparison
The table below maps the operations a rotation pipeline actually performs to how each tool handles them. It is deliberately even-handed: Curator retains genuine advantages for a handful of tasks that fall outside ILM’s declarative model.
| Capability | Curator (external cron) | ILM (internal state machine) |
|---|---|---|
| Rollover | rollover action; you invoke it and it evaluates conditions once per run | rollover action in the hot phase, re-evaluated every poll until a condition trips |
| Delete by age | delete_indices with an age filter on creation_date — arbitrary patterns, no policy needed | delete phase with min_age measured from rollover, only on managed indices |
| Forcemerge | forcemerge action, filtered by age; runs on the cron tick regardless of load | forcemerge action in warm/cold, ordered after allocation, paced by the coordinator |
| Shrink | shrink action, requires manual primary co-location beforehand | shrink action; ILM allocates a copy of every shard to one node first, automatically |
| Snapshot | snapshot action on a schedule; retention via a separate delete_snapshots run | searchable_snapshot action plus SLM for scheduled snapshots and retention |
| Allocation awareness | None — issues calls blind to watermarks and shard state | Native — pauses transitions when a target tier is full or a shard cannot move |
| Survives restart | No — state lives in cron; a missed window is simply skipped | Yes — policy and per-index step state are cluster metadata, resumed after restart |
| Scheduling model | External cron, fixed wall-clock times | Internal poll loop, event-driven per index from the rollover clock |
| Failure handling | Action aborts, logged externally, retried on next cron tick | Per-index ERROR step, isolated, auto-retried each poll after the cause clears |
Two rows deserve emphasis. Curator’s delete-by-age against arbitrary index patterns with no policy attached is something ILM does not do natively — ILM only deletes indices it manages, through their own delete phase. And Curator’s snapshot scheduling has a direct successor not in ILM but in Snapshot Lifecycle Management (SLM), which is the correct target for the snapshot half of a Curator config. Rollover, delete, forcemerge, and shrink all map cleanly onto ILM phases; snapshot scheduling maps onto SLM; and a small residue of ad-hoc maintenance stays with Curator or a bespoke script.
Configuration Reference
The clearest way to see what maps and what changes is to place an illustrative Curator action file beside the ILM policy that reproduces its behaviour. The Curator YAML below is a representative rotation for a syslog-* pipeline — rollover the write alias, force-merge indices older than two days, delete indices older than ninety:
# /etc/curator/actions/syslog.yml — illustrative legacy config
actions:
1:
action: rollover
options:
name: syslog-write
conditions:
max_age: 1d
max_primary_shard_size: 50gb
2:
action: forcemerge
options:
max_num_segments: 1
filters:
- filtertype: age
source: creation_date # age from creation, not rollover
direction: older
unit: days
unit_count: 2
3:
action: delete_indices
filters:
- filtertype: pattern
kind: prefix
value: syslog-
- filtertype: age
source: creation_date
direction: older
unit: days
unit_count: 90The equivalent ILM policy folds all three actions into one declarative document. Each Curator action becomes a phase; the filter chains become min_age boundaries; and the rollover conditions move verbatim into the hot phase:
PUT _ilm/policy/syslog-ilm
{
"policy": {
"phases": {
"hot": {
"min_age": "0ms",
"actions": {
"rollover": {
"max_age": "1d",
"max_primary_shard_size": "50gb"
},
"set_priority": { "priority": 100 }
}
},
"warm": {
"min_age": "2d",
"actions": {
"forcemerge": { "max_num_segments": 1 },
"set_priority": { "priority": 50 }
}
},
"delete": {
"min_age": "90d",
"actions": { "delete": {} }
}
}
}
}Two differences are load-bearing, not cosmetic. First, the Curator forcemerge and delete_indices filters compute age from creation_date, whereas the ILM warm and delete phases compute min_age from the rollover event. If a syslog-* index takes three days to fill and roll, its ILM delete clock starts three days later than the Curator equivalent would have. Reproduce the intended retention, and validate it, rather than copying the number blindly. Second, ILM runs actions within a phase in a fixed internal order — allocation and priority before destructive actions — so you cannot reorder them by rearranging the JSON the way you sequenced numbered Curator actions.
Step-by-Step Migration Outline
Migrating a running pipeline is a sequencing problem: the ILM policy must take ownership of the indices before the Curator cron is retired, but never in a window where both tools could act on the same index. The outline below is the high-level shape; the full, race-safe runbook — including how to attach the policy to indices that already exist — lives in migrating from Curator to ILM policies.
- Map each Curator action to an ILM phase. Rollover conditions go to the hot phase unchanged;
forcemergeandshrinkfilters become warm-phase actions with amin_age; thedelete_indicesage filter becomes the delete phasemin_age. Snapshot actions move to an SLM policy, not ILM. - Create the policy. Apply
syslog-ilmwithPUT _ilm/policy/syslog-ilm(orilm.put_lifecycle). Creating the policy is inert — it manages nothing until an index references it, so this step is safe to run while Curator is still live. - Attach via a composable template. Add
index.lifecycle.name: syslog-ilmandindex.lifecycle.rollover_alias: syslog-writeto the index template so every new backing index is managed from creation. A template alone does not touch existing indices. - Adopt existing indices, then retire the cron. Attach the policy to indices that already exist with
PUT <index>/_settings, confirm they reportmanaged: true, and only then disable the Curator cron entry. Retiring the cron before adoption leaves a gap where nothing rotates; retiring it after adoption without care risks a window where both act. - Verify and decommission. Confirm every
syslog-*index is managed and progressing, watch one full rollover happen under ILM, then remove the Curator package and its config from the host.
Verification
Confirm ILM has genuinely taken ownership before you trust it. First, check that the indices Curator used to manage are now managed by the policy:
GET syslog-*/_ilm/explain{
"indices": {
"syslog-000007": {
"index": "syslog-000007",
"managed": true,
"policy": "syslog-ilm",
"phase": "hot",
"action": "rollover",
"step": "check-rollover-ready"
}
}
}"managed": true with "policy": "syslog-ilm" confirms adoption; an index reporting "managed": false is still orphaned and will be rotated by neither tool once the cron is gone. Next, confirm the ILM service itself is running, since a stopped coordinator silently freezes every managed index:
GET _ilm/statusA response of { "operation_mode": "RUNNING" } means the state machine is live. Finally — and this is the step migrations skip at their peril — confirm the Curator cron is actually disabled on the host, so it cannot fire a second delete against indices ILM now owns:
# The syslog Curator entry must be gone (or commented out).
crontab -l | grep -i curator
systemctl list-timers | grep -i curatorBoth commands should return nothing. If either still shows an active schedule, you are running both systems against the same indices — the dangerous state described next.
Decision Guidance: When Each Tool Wins
Migration is not an unconditional verdict against Curator. For the recurring lifecycle of managed time-series data, ILM wins decisively; for a narrow band of one-off and out-of-band tasks, Curator (or a small bespoke script) remains the pragmatic choice.
ILM wins when the work is the ongoing lifecycle of indices that share a policy: rolling over on size or age, migrating between data tiers, force-merging and shrinking on a schedule tied to the rollover clock, and deleting at end of retention. Here ILM’s allocation awareness, restart durability, per-index failure isolation, and native data-tier and searchable-snapshot integration are advantages Curator structurally cannot match, because Curator runs outside the master and cannot see allocation state. Anything that should “just keep happening” to every index in a stream belongs in ILM.
Curator (or an equivalent script) still earns its place when the task is genuinely ad-hoc or falls outside the managed-index model. Deleting a set of indices by an arbitrary name pattern that was never attached to a policy — cleaning up an abandoned experiment, purging a one-off backfill, dropping indices from a decommissioned tenant — is something ILM does not do, because ILM only deletes what it manages. Curator’s rich filter chains (by pattern, by space, by count, by creation_date) are still the fastest way to express a one-shot bulk operation. Some teams keep a minimal Curator install purely for these out-of-band cleanups long after ILM owns the routine rotation. That is a legitimate division of labour, not a migration failure. The point is to stop using Curator for recurring lifecycle work — where a missed cron tick means silent retention drift — and reserve it for deliberate, human-invoked maintenance.
Troubleshooting
Double-management: both Curator and ILM acting on the same indices
Symptom: indices roll over or delete at unexpected times; ILM _ilm/explain shows an index that vanished mid-step, or an index rolls twice in quick succession. The root cause is that the Curator cron was never disabled after the ILM policy was attached, so two independent controllers are mutating the same indices. Resolution:
- Disable the Curator cron immediately —
crontab -eand remove the entry, orsystemctl disable --nowthe timer. - Re-run
GET syslog-*/_ilm/explainand repair any index left in anERRORstep withPOST /<index>/_ilm/retryafter confirming the cause is cleared. - Audit the Curator logs for the overlap window to confirm no index was deleted prematurely; restore from snapshot if a retention breach occurred.
Overlapping deletes race and delete twice (or a shard mid-move)
Symptom: a delete lands while ILM is relocating the index to a colder tier, producing index_not_found_exception in ILM’s step logs, or an index Curator expected to delete is already gone. Resolution:
- Enforce the ordering rule: only one system may hold the delete phase at a time. Stop Curator’s
delete_indicesaction before ILM’sdeletephase can reach the same age boundary. - If an index was deleted during a relocation, ignore the transient
index_not_found_exception— the index is gone, which was the intent — but confirm no in-retention index was caught by the wider Curator pattern. - Narrow the Curator delete filter to a pattern that cannot overlap managed indices (for example, only unmanaged legacy names) if you intend to keep Curator for cleanup.
Existing indices ignore the new policy
Symptom: new syslog-* indices are managed, but older ones created before the template change report "managed": false and never transition. Resolution:
- A composable template only affects indices created after it is applied. Attach the policy to existing indices explicitly with
PUT <index>/_settingssettingindex.lifecycle.name(and the rollover alias on the current write index). - Confirm each adopted index reports
"managed": truein_ilm/explain. - The full adoption procedure, including the ordering that prevents a double-delete race, is covered in migrating from Curator to ILM policies.
FAQ
Is Curator deprecated, and do I have to migrate?
Curator is no longer the recommended tool for index lifecycle work, and active development has wound down in favour of ILM and SLM, which are built into Elasticsearch. You are not forced to migrate, but a cron-driven external tool cannot see allocation state, does not survive its own missed runs, and does not integrate with data tiers or searchable snapshots. For recurring rotation of a stream like syslog-*, ILM is the maintained path; Curator can stay for genuine one-off maintenance.
Does my Curator retention window translate exactly to an ILM min_age?
Not automatically. Curator age filters usually compute from creation_date, while ILM min_age in warm, cold, and delete phases is measured from the rollover event. An index that spends days filling before it rolls will reach its ILM delete boundary later than the equivalent Curator rule would have fired. Reproduce the intended retention and verify it with _ilm/explain, rather than copying the day count verbatim.
Can I run Curator and ILM at the same time during the transition?
Only if they act on strictly disjoint sets of indices. Two controllers mutating the same index is the double-management failure mode: overlapping deletes race, and rollover can fire twice. The safe pattern is to attach the ILM policy, confirm the indices are managed, and only then disable the Curator cron for those indices — never leave both live against the same pattern.
What happens to my Curator snapshot action?
The snapshot half of a Curator config maps to Snapshot Lifecycle Management (SLM), not to ILM. SLM schedules snapshots and enforces retention declaratively, the same way ILM handles index rotation. ILM’s own searchable_snapshot action is a different thing — it mounts an index from a repository to back the cold or frozen tier — and does not replace scheduled backup snapshots.
Is there anything ILM genuinely cannot do that Curator could?
Yes: deleting or force-merging arbitrary indices by name pattern that were never attached to a policy. ILM only acts on indices it manages, so a one-off bulk cleanup of unmanaged legacy indices is still easier with Curator’s filter chains or a small script. That residual use is legitimate; the migration goal is to move recurring lifecycle work to ILM, not to eliminate every script.
Related
- Migrating from Curator to ILM Policies — the race-safe runbook for handing existing indices to ILM without a double-delete.
- Configuring Index Rollover Conditions — the hot-phase triggers that replace a Curator rollover action.
- Monitoring ILM Health with cat and explain APIs — confirming managed indices progress after the cutover, where Curator left only cron logs.
- Index Lifecycle Management (ILM) — the control plane whose reconciliation model underlies every difference above.
← Back to ILM Architecture & Fundamentals