Product Decisions This Supports
Guardrail / governance, not a feature. This package doesn't add user-facing capability — it removes a footgun. It disables Doctrine's doctrine:schema:update console command so schema changes can only land through migrations. That makes it relevant to a narrow but important set of decisions:
- Deployment safety posture. Do we allow ad-hoc schema mutations against shared, staging, or production databases, or do we require every schema change to be a reviewed, versioned, replayable artifact? Adopting this answers "no" and enforces it mechanically instead of via wiki pages and code-review vigilance.
- Migration discipline / audit trail. Schema changes become diffable, reviewable, revertible, and correlated with a release. That supports incident forensics ("what changed the DB during this deploy?") and compliance/audit conversations (SOC 2 change management, ISO 27001) where "a developer ran a CLI command" is not an acceptable control.
- Environment parity and drift.
schema:update silently converges a database to whatever the entity mapping currently says, which is how dev, staging, and prod quietly diverge. Forcing migrations makes drift visible as a failing migration rather than a mysterious behavior difference found in production.
- Onboarding and team scaling. The command is a convenience that rewards individual velocity and punishes team coordination. Removing it is a decision to optimize for the second-through-twentieth engineer, and for the on-call rotation.
- Build vs. buy. The behavioral surface is roughly "remove/override one console command and fail loudly if someone tries to use it." That's a compiler pass plus a service override — on the order of tens of lines. Treat this as build or fork, not buy: the concept is the product decision; this specific artifact is a reference implementation.
Important scoping caveat: this is a Symfony bundle built on Doctrine, not a Laravel package. If the codebase in question is Laravel/Eloquent, this is largely a non-decision — Laravel's schema tooling is migration-first by default and there is no doctrine:schema:update equivalent to disable. Its decision value there is conceptual only: "do we have any tool that can mutate shared schema outside migrations, and should we close it?" (e.g., migrate:fresh, ad-hoc Schema:: calls in tinker, seeders in production). Do not attempt to adopt the package itself into a Laravel app.
Health signals: 0 stars, 0 dependents, last release March 2016. This is effectively an abandoned, single-purpose artifact. The decision is sound; the dependency is not.
When to Consider This Package
Consider the approach when:
- The stack is Symfony + Doctrine ORM and
doctrine:schema:update is genuinely reachable in staging or production (it often is — the command ships by default).
- You have evidence of the problem: incidents, near-misses, schema drift between environments, or migrations that were bypassed because "it was faster to just update the schema."
- You need a cheap, immediate stopgap while a proper CI/deploy-pipeline control is built. Overriding or removing a console command is a one-afternoon change and immediately visible.
- You want a mechanical control rather than a policy document, because your team has already agreed on the policy and the gap is enforcement.
Look elsewhere — or build the equivalent — when:
- Any Laravel/Eloquent application. Not applicable; the command doesn't exist. Solve the analogous problem (production seeding,
migrate:fresh on shared DBs, direct Schema calls) with environment guards and pipeline permissions instead.
- You are on a modern Symfony version. A 2016 bundle predates Symfony 4/5/6/7, Flex, and autowiring. Wiring it in will cost more in compatibility work and debugging than reimplementing it. Symfony's DI container already lets you remove or override the command via a small compiler pass — zero third-party surface.
- You want a maintained dependency. 0 stars / 0 dependents / 9-year-old last release means no security response, no Symfony compatibility guarantee, and no one to escalate to. That is unacceptable for anything in a deploy path.
- Your real problem is pipeline permissions, not developer tooling. If engineers hold credentials to production databases, disabling a CLI command is security theater — they can still run raw SQL. Fix the access model first; this package is a complement, never a substitute.
- You need more than a kill switch — e.g., drift detection (comparing live schema to mapping in CI), migration review gates, or rollback verification. This package does none of that.
Recommended default: adopt the decision, not the dependency. Reproduce the guardrail in-house with an explicit, documented compiler pass or command override, covered by a test that asserts the command is unavailable in non-dev environments. Forking is acceptable if you want the reference behavior — MIT license makes that clean — but budget for it being unmaintained from day one.
How to Pitch It (Stakeholders)
For executives — the one-liner: This is a low-cost safety control that prevents an entire class of production database incidents by making sure every schema change is recorded, reviewed, and reversible. It closes a door that developers have historically been able to walk through.
The business case:
- Risk reduction, not capability. Database schema is the hardest thing to roll back and the easiest thing to break irreversibly. A single accidental schema mutation against production can mean data loss, extended downtime, and a very expensive recovery. Restricting schema changes to migrations converts that from a possible event into a near-impossible one.
- Auditability. Every schema change becomes a reviewed artifact tied to a release. That's what auditors and post-incident reviews ask for, and it's what we currently can't reliably produce.
- Cost is trivial — the control is small and the license is permissive — but the off-the-shelf artifact is not the recommendation. The package is unmaintained (last release 2016, no adopters). We should implement the same guardrail internally, roughly a day of engineering, and own it. Recommending we depend on an abandoned library in a deploy path would be a bigger risk than the one we're mitigating.
- Scope honesty: this applies to our Doctrine-based Symfony services. It does not apply to our Laravel services, where migrations are already the default path — for those the equivalent conversation is about database access controls and production seeding, which we should handle separately.
For engineering — the ask:
- One small, tested change: remove or override the
doctrine:schema:update command in non-dev environments, and fail loudly if invoked. No third-party dependency required; a compiler pass plus a test asserting the command's absence gets us there.
- Keep the escape hatch in local dev, where fast iteration is legitimate.
- Pair it with the thing that actually matters: production database credentials should not be held by individuals running console commands. The command removal is defense-in-depth, not the control itself.
- Reference
webtown/doctrine-schema-update-bundle as prior art for the behavior and expected error semantics, not as a dependency.
Bottom line: approve the decision (migrations only, enforced), reject the dependency (abandoned), and scope it to the Doctrine/Symfony services only.