Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Release Phase Migrations Bundle Laravel Package

fervo/release-phase-migrations-bundle

A Symfony bundle for Doctrine migrations that adds release phases, letting you group schema and data changes and run them in a controlled order during deployment. Tag migrations by phase, run the right set per release, and keep deployments predictable across environments.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit — poor as an artifact, sound as a pattern. This is a Symfony bundle, not a Laravel package. It ships a Bundle subclass, DI extension, and YAML configuration — none of which have any meaning in Laravel's service-provider model. Zero code is directly reusable; what transfers is the idea, which is roughly 150–250 lines of logic.

The idea is: acquire a database-native advisory lock, run migrations, release. The naming points to release-phase execution (e.g., Heroku release dynos, or a Kubernetes Job/init container), where N deploy replicas may attempt migrations simultaneously against one database. That concurrency problem is real for Laravel shops deploying multiple containers, and Laravel has no built-in answer.

Integration feasibility — low for the package, high for the pattern. Laravel's migrate command already sits on symfony/console, so wrapping it via $this->call('migrate') is trivial. The actual work is driver-specific lock semantics:

  • Postgres: pg_try_advisory_lock(key) / pg_advisory_unlock(key) — session-scoped
  • MySQL: GET_LOCK(name, timeout) / RELEASE_LOCK(name) — connection-scoped
  • SQL Server: sp_getapplock / sp_releaseapplock
  • SQLite: no advisory lock; file lock or no-op

A Cache::lock() alternative exists but is materially worse for this use case: cache locks carry a TTL, and a migration exceeding that TTL lets a second runner proceed mid-DDL. Database advisory locks die with the session, which is the correct failure semantic.

Technical risk — high, concentrated in abandonment. Last release 2021-10-06, 5 stars, 0 dependents, score 0.055. There is no community validation, no maintainer signal, and Doctrine Migrations major versions since then will likely break its version constraints outright. Adopting the package means adopting a dead dependency that does not even target our framework. Supply-chain exposure is negligible (small surface), but the fork-and-own cost is not.

Key questions for the team:

  1. Which production database, and do we connect through a pooler (PgBouncer transaction mode silently breaks session-level advisory locks)?
  2. How many concurrent deploy replicas actually run migrations today?
  3. On lock contention: fail fast or block with timeout? What is the deploy pipeline's timeout budget?
  4. Is the requirement concurrency safety or zero-downtime schema change? These are different problems — this package only addresses the first.

Integration Approach

Stack fit. Laravel 10/11, PHP 8.2+, Postgres 14+ or MySQL 8+, container deploys with ≥2 replicas and a release/init step. The pattern fits; the package does not.

Migration path — do not adopt, reimplement. Recommended: an internal php artisan migrate:locked command that opens a dedicated connection, runs the driver-appropriate try-lock with a bounded wait, invokes migrate --force, and releases in a finally block. Roughly 2–4 engineer-days including tests. Forking the bundle and porting it to Laravel is 5–8 days and leaves us owning a Symfony artifact with a stale Doctrine dependency — strictly worse.

Compatibility. Low friction on our side. The bundle's only real constraint (Doctrine Migrations) is irrelevant to us since Laravel migrations replace it. The underlying Symfony Console layer is already present in every Laravel app, so the command-wrapping approach inherits no new dependencies.

Sequencing.

  1. Spike on staging: two concurrent runners, verify exactly one executes, measure lock wait.
  2. Implement the lock helper + migrate:locked with configurable timeout.
  3. Wire into the deploy pipeline ahead of traffic shift; keep migrate available as a manual escape hatch.
  4. Add timeout and lock-failure alerting before enabling in production.
  5. Publish a runbook covering "lock held, deploy stalled."

Design the lock key per database, not per application — advisory_lock.deploy_migrations or equivalent — so unrelated apps on a shared instance do not collide.

Operational Impact

Maintenance. Zero upstream maintenance. Whether we fork or reimplement, we own it permanently; the reimplementation is small enough that ownership is cheap. Add a quarterly review to confirm lock behavior still matches driver versions.

Support. No vendor, no docs beyond a README, no issue activity. Internal SME required. That is unavoidable for either path, but a self-written 200-line command is far easier to hand to a new engineer than a ported Symfony bundle.

Scaling. Advisory locks are per-session and scale fine to N deploy replicas. Two caveats dominate: connection poolers in transaction mode break session locks (lock acquired and released within a pooled transaction, or not at all), and very long migrations hold a lock while blocking other deploys. Cap migration runtime and treat the lock timeout as a hard pipeline failure.

Failure modes to plan for:

  • Process crash mid-migration — session drops, DB releases the lock automatically. Correct behavior; no manual cleanup.
  • Lock leak through a pooler — the worst case; validate pooler mode explicitly, or bypass the pooler for the migration connection.
  • Deploy hang on contention — bounded wait + non-zero exit + pipeline alert.
  • Migration succeeded but app incompatible — locking does not solve this. Expand/contract discipline is still required; the lock only prevents two runners from racing the same DDL.
  • Partial migration failure — Laravel's per-migration transaction behavior varies by driver (MySQL DDL is non-transactional). The lock guarantees single execution, not atomicity.

Ramp-up. Low for the command itself, moderate for the operational knowledge — driver-specific lock semantics, pooler interactions, and runbook judgment when a deploy stalls. Budget half a day of platform-team onboarding and a written runbook before production enablement.

Recommendation: reference the bundle as prior art, reimplement the pattern internally, and treat the 0.055 score and 2021 release date as disqualifying for direct adoption.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route