boutdecode/etl-core-bundle
Symfony bundle for building configurable ETL pipelines with reusable Workflow templates and time-bound Pipeline runs. Chains Extract, Transform, and Load steps via Symfony Messenger, Workflow, and Flow-PHP, with DDD/CQS structure, status tracking, and per-run configuration overrides.
Architecture fit — framework mismatch is the headline. Despite the "Laravel/PHP" framing, this is a Symfony bundle (boutdecode/etl-core-bundle), not a Laravel package. It hard-depends on Symfony 6.4/7.x, Symfony Messenger buses, Symfony Workflow state machines, and Doctrine ORM 3.6. There is no service provider, no config publishing, no Laravel-native integration. Any Laravel team evaluating this should treat it as "Symfony-only, not applicable without a bridge" — and a Symfony-in-Laravel bridge would be a self-inflicted architectural compromise, not a TPM-approved integration path.
If the target stack is Symfony, the architecture is actually well-conceived for a data-pipeline engine:
Workflow → Pipeline), which maps well to operational concepts of "reusable recipe" vs "one run with an audit trail."Domain/ vs Infrastructure/ boundaries and CQS command/query buses — defensible for teams already fluent in it.#[AsExecutableStep] tag + StepResolver, plus ordered middleware chains at pipeline and step level.pending → in_progress → completed/failed) with timestamps and history entities — that is the right shape for an auditable ETL platform.Integration feasibility — moderate-to-heavy. The bundle ships no Doctrine entities; you must author five concrete entities (Workflow, Step, Pipeline, StepHistory, PipelineHistory) extending abstract bases, re-declare ORM mappings on inherited properties, add an $id per entity, and generate migrations yourself. That is meaningful boilerplate and a standing coupling surface: when the bundle's abstract bases change, your entity mappings may break. The bundle also exposes no configuration keys — all service IDs, tags, and bus names are fixed constants (boutdecode_etl_core.command.bus, etc.). That means no namespacing freedom and no ability to avoid collisions with your own buses.
Technical risk — high on supply-chain, low on code quality.
^3.6 (excludes the vast majority of running Doctrine 2.x apps), Flow-PHP ~0.25 (pre-1.0, breaking-change-prone), PHP 8.2–8.4, Symfony 6.4/7.x. Each of these is a hard gate.declare(strict_types=1), PSR-12, PHPStan/ECS/PHPUnit in CI, stated baseline of 243 unit + 3 integration tests, documented architecture rules. Code discipline appears above what 2 stars implies.Key questions to resolve before any commitment:
~0.25 have a stable upgrade story, or will it drag breaking changes into our pipeline engine?Stack fit. Only viable if the host application is Symfony 6.4/7.x with Doctrine ORM 3.6 and Messenger already configured. For a Laravel codebase this should be classified not a fit — do not attempt a laravel-symfony bridge for a core data path; the failure modes (container duality, duplicate buses, service-tag collisions, migration ownership) outweigh the reuse benefit.
Migration path (Symfony-native).
AbstractExtractorStep / AbstractTransformerStep / AbstractLoaderStep subclasses. Keep step logic in your app, not forked into vendor.PipelineHistory/StepHistory tables give you the audit trail to do this comparison honestly.resolved_target_entity inheritance mapping to "save boilerplate." The docs intentionally require concrete entities; fighting that will produce brittle mappings.Compatibility gates to check in order (fail fast):
>= 8.2 — usually fine.^6.4 || ^7.0 — hard gate.^3.6 — the most likely blocker; many Symfony apps still run ORM 2.x.~0.25 — verify no conflict with existing flow-php constraints (composer why-not).command.bus / query.bus / event.bus — confirm no ID collision with application buses.Sequencing recommendation (4 phases):
PipelineHistory status counts.Where to invest engineering effort: the entity layer (yours) and the step implementations (yours) are the real maintenance burden; the bundle is a thin orchestration shell. Budget accordingly.
Maintenance. The dominant risk is single-maintainer / 2-star / 0-dependent status. Even with clean code, a TPM must assume the bundle will not receive timely security or compatibility patches. Mitigations: pin exact versions, fork the repo internally as a contingency, and avoid forking features into vendor — keep all custom logic in your own ExecutableStep classes and middleware so an internal fork or replacement remains cheap. The fixed bus and tag constants and abstract base classes you extend are the two coupling points that make replacement non-trivial; document them explicitly as your "exit cost" inventory.
Support. Community support is effectively nil. Knowledge must be internalized through the spike; the AGENTS.md and README are better than average for this maturity level, but you cannot rely on upstream responsiveness. Plan for one named owner (or a pair) to hold the ETL engine's institutional knowledge.
Scaling. Two separate concerns:
PipelineHistory and StepHistory with json input/result columns will grow unboundedly. Without a retention policy and archiving job, this becomes a database-size problem in months, not years. Budget for partitioning or periodic archival from day one.Failure modes to instrument and test explicitly:
in_progress after a worker crash. Needs a reaper/reconciler.configuration, so verify how it composes with transport-level retries.mixed input/result stored as JSON; large payloads or non-serializable objects will fail at persistence, not at step execution. Add a payload-size guard.PipelineScheduler on Symfony Scheduler is fine in a single-worker setup; multi-worker deployments need to confirm no double-scheduling.Ramp-up. Non-trivial for teams new to DDD/CQS/middleware. Expect 2–4 weeks for a mid-level Symfony engineer to become productive on the entity + step model, and another 2–3 weeks to be confident with middleware ordering, the workflow state machine, and Messenger async semantics. The template-vs-instance (Workflow vs Pipeline) and config-vs-execution (Step vs ExecutableStep) distinctions are the concepts most likely to cause early design mistakes; front-load those in onboarding.
TPM recommendation. For a Symfony 6.4/7 + Doctrine 3.6 team with a genuine need for a configurable, auditable ETL engine and appetite to own the entity layer, this is a justifiable pilot — architecture is sound and code discipline is credible. For a Laravel team, or a team on Doctrine 2.x, or any team without capacity to own a fork contingency, this is a do not adopt. The score (~23.8) and adoption signals (2 stars, 0 dependents) should be treated as go/no-go context, not as a code-quality verdict.
Opportunity note: the opportunity score of 27.95 suggests the underlying problem space (configurable, auditable Symfony ETL orchestration) is under-served. That argues for a thin internal wrapper around this bundle — or a build-vs-adopt evaluation of Flow-PHP directly — rather than an unbounded dependency on a single-maintainer package.
How can I help you explore Laravel packages today?