Technical Evaluation
What it actually is: a thin adapter, not a scheduler. It wires the cron/cron expression library into an Ibexa/Symfony application behind a single console command (ibexa:cron:run) plus a DI service tag (ibexa.cron.job) carrying schedule and optional category. There is no queue, no persistence, no run history, no locking, and no administration UI. The command is designed to be polled every minute by the host system's cron.
Architecture fit
- Fits only where an Ibexa DXP kernel already boots. The README's "or just plain Symfony" claim is aspirational: taking this dependency into a non-Ibexa app buys you an Ibexa-flavored configuration surface over the same library you could consume directly in an afternoon.
- The design is deliberately opinionated toward "one crontab entry, many tagged jobs." That is a clean fit for a DXP where editorial/product teams want job definitions to travel with the code rather than live in an ops-managed crontab.
- It is explicitly not a replacement for
cron/cron-bundle. Treat it as an internal Ibexa component published for consumption inside the DXP distribution.
Integration feasibility
- Low effort:
composer require, tag existing Symfony commands, add one crontab line. No schema, no new infrastructure, no sidecar.
- The hard part is not code, it is governance: somebody must own schedules as code, and the "category" concept must be defined before the first tag is written or it becomes tribal knowledge.
Technical risk
- License is the gating risk.
NOASSERTION means automated compliance cannot clear it. Ibexa's ecosystem is historically copyleft; this must be resolved with legal before any distribution or OEM scenario. Do not treat as low-risk until confirmed.
- No overlap guard and no lock. Nothing prevents two invocations running concurrently, and nothing coordinates multiple application nodes. README concedes cluster support is future work.
- Stateless polling. A job fires only if the command happens to execute during a matching minute. If the host is down, deploys, or the command is slow, that window is lost with no catch-up.
- Poor failure visibility by default. The README's own crontab example redirects to
/dev/null 2>&1, which discards exactly the output you need when a job silently stops running.
- Adoption signal is weak: 3 stars, 0 dependents, single-word typo in the README ("simle"). This is an internal utility with a public URL, not a community-vetted library. Its health is tied to Ibexa's release cadence.
- Metadata anomaly: a last-release date of 2026-08-20 should be verified on Packagist before it is used as a trust signal in any decision record.
Key questions
- Are we already on Ibexa DXP, and does the metapackage pull this in transitively? If yes, most of this evaluation is moot — we are not adopting, we are configuring.
- What is the license, in writing, from Ibexa or from the repository's
composer.json?
- What is our node topology, and do we have an infrastructure-level mutex (single designated cron node,
flock, or a Kubernetes CronJob with concurrencyPolicy: Forbid)?
- Which existing scheduled work — platform maintenance tasks, imports, exports, index rebuilds — moves here, and who signs off on each schedule?
- Do we require retries, alerting, or run history? If yes, this package is a stopgap and we should plan for
symfony/scheduler or a job runner.
- Is
category being used to separate schedule cadence or execution topology (all-nodes vs one-node)? Those need different mechanisms; only the former is supported today.
Integration Approach
Stack fit
- Requires: Ibexa DXP (v4.x-era) or a Symfony console app with the Ibexa DI conventions, PHP version aligned to the pinned Ibexa release, and
cron/cron as a transitive dependency.
- Non-fit: any service that is not Ibexa, any environment where per-minute process spin-up is expensive or prohibited, any workload needing exactly-once semantics.
Migration path
- From raw system crontab: inventory every line, convert each to a tagged command with an equivalent schedule expression, then collapse N crontab entries to one. This is the main win — schedule ownership moves into the repo and into code review.
- From
cron/cron-bundle: functionally overlapping. Migrate only if you want consistency with Ibexa conventions; otherwise the bundle's richer feature set is the better default.
- From legacy Ibexa
ezplatform:cron:run: confirm the command rename and tag name against your target DXP version before planning the change window.
Compatibility
- Pin the package version and re-verify on every Ibexa/Symfony major upgrade. Because this is a first-party subpackage, its version constraints usually track the platform — accept that coupling or fork.
- Verify that the DI tag compiler pass is active in your kernel; a silently unregistered tag means jobs that simply never run, with no error.
Sequencing
- License clearance (legal) — hard gate, before any code lands.
- Job inventory and ownership — list every scheduled task, its current cadence, expected duration, and whether it is single-node or all-node.
- Category taxonomy — define a small, closed set (
default, frequent, maintenance, single-node) and document it. Do not let categories proliferate.
- Staging pilot — require only two or three low-risk jobs, run the command manually and observe emission, then run it from a one-minute crontab for a week.
- Cutover — disable old crontab lines in the same change window you enable the new entry, so nothing runs twice. Do not run both in parallel "to be safe."
- Instrumentation pass — replace
/dev/null with a logger or log shipper; capture exit code and wall-clock duration per job.
Exit plan: cheap. Because the surface is a tag and a command, reverting means re-registering crontab lines or moving to symfony/scheduler. Keep the inventory document from step 2 current — it is your rollback asset.
Operational Impact
Maintenance
- Very low code surface: one command, one compiler pass, dependency on
cron/cron. No migrations, no storage, no schema.
- The real maintenance cost is version-coupled: every Ibexa DXP upgrade is also a review of this package. Budget a few hours per upgrade cycle, not per month.
- With 3 stars and no dependents, expect to be your own first-line support. Stack Overflow coverage for this package specifically is effectively nil; the underlying
cron/cron library is where community answers exist.
Support
- Upstream is Ibexa; meaningful support comes only with a commercial DXP subscription. Otherwise you rely on the repository's issue tracker and your own engineers.
- The tiny surface area is a mitigation: a mid-level Symfony developer can read the whole implementation in under an hour and patch a fork if needed.
Scaling
- The design is per-minute, stateless, single-process. Throughput is bounded by how many tagged commands can complete inside the minute window.
- No locking, no clustering. On a multi-node deployment, every node runs the command and every job fires once per node. The README is unambiguous that cluster semantics are future work. Mitigate outside the package: run the entrypoint on exactly one designated node, wrap in
flock, or use a Kubernetes CronJob with concurrencyPolicy: Forbid and startingDeadlineSeconds set deliberately.
- Categories are a routing label, not a coordination mechanism. Do not use them as a proxy for "run only on one node."
Failure modes to design around
- Overlap: a job exceeding ~60s overlaps the next invocation. No guard exists; add
flock or enforce a runtime budget per job.
- Missed windows: a deploy, restart, or slow command at the wrong minute means the job is skipped permanently. For anything that must run daily, add a compensating check or alert on absence-of-success rather than presence-of-failure.
- Silent failure: the README's
>/dev/null 2>&1 hides everything. Always ship output to a monitored sink.
- Head-of-line blocking: if jobs run serially in one invocation, a slow job delays or starves subsequent jobs in the same run. Order and categorise accordingly.
- Timezone drift: cron expressions evaluate against the PHP process timezone. Pin it explicitly, or DST transitions will move your jobs by an hour twice a year.
- Registration failure: a mistyped tag name fails silently — the job is never enqueued. Add a startup assertion or a scheduled count check.
Ramp-up
- Developer ramp-up: under a day. Tag a command, add a schedule, run the console command, observe.
- Operational ramp-up: longer, and it is cultural, not technical. The team must accept schedules-as-code, agree the category taxonomy, own per-job runtime budgets, and have a documented answer to "which node runs this." Codify that in a one-page internal standard before the pilot; it is the difference between a tidy consolidation and an unobservable pile of invisible jobs.
Bottom line for the decision record: approve only as a configuration of an existing Ibexa DXP footprint, contingent on license clearance and an infrastructure-level single-runner guarantee, with logging wired up from day one. If we are not on Ibexa, or if we need retries, run history, or clustered scheduling, this is the wrong tool — standardize on symfony/scheduler or cron/cron-bundle instead and revisit if Ibexa ships the promised lock and cluster semantics.