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

Laravel Sequence Laravel Package

hatchyu/laravel-sequence

A Laravel package for generating customizable, concurrency-safe sequential numbers for invoices, orders, and other records. Database-backed sequences support configurable formats, prefixes, reset schedules, and easy model integration, helping you create human-readable IDs without collisions.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

The package targets a well-known gap in Laravel: the framework ships auto-incrementing primary keys but nothing for human-facing sequential identifiers (invoice numbers, order numbers, ticket IDs) that must be gapless-ish, scoped, and formatted. The described design — a dedicated sequence table, a transaction wrapping SELECT ... FOR UPDATE on a row keyed by a grouping column, an increment, and a formatter — is the conventional and correct approach for this problem. It fits Laravel's package conventions cleanly: service provider, publishable config and migration, and a model trait for booted()-time assignment. That means low coupling to application code and an easy exit path. Grouping (per tenant, per document type, per year) and formatting (prefix, padding) are the two features that actually drive adoption in this category, so the feature surface is aimed at real use rather than novelty. The main architectural caveat is that the lock is a serialization point: every writer in a group queues behind one row. That is fine for orders and invoices; it is wrong for high-volume event or log identifiers.

Integration feasibility

Integration cost is low on paper: composer require, publish migration/config, add a trait or call a facade inside an existing transaction. No queue worker, no external service, no new infrastructure. The hard part is not installation, it is semantics. Two questions determine whether it drops in or requires rework: (1) does the package open its own transaction, or does it enlist in the caller's? and (2) what happens to the counter when the caller's transaction rolls back? If the counter increments in its own committed transaction, you get gaps on rollback (usually acceptable, often contractually not). If it shares the caller's transaction, gaps disappear but the row lock is held for the entire duration of the caller's work, which materially raises contention and deadlock exposure. Neither answer is universally right, but the choice must be known before design sign-off.

Technical risk

  • Maturity signal. 6 stars, 0 dependents, single-author repo. There is no production corpus to lean on and no evidence of third-party hardening. Treat the code as unaudited until reviewed.
  • Database portability. Row-level locking is not uniform. MySQL/InnoDB and PostgreSQL behave differently under FOR UPDATE (gap locks vs. row locks, REPEATABLE READ vs. READ COMMITTED), and SQLite has no FOR UPDATE at all — it degrades to a database-wide write lock. Dev-on-SQLite / prod-on-MySQL is the classic way this class of package fails in production while passing CI.
  • Deadlock and lock-wait exposure. Multi-group acquisition in inconsistent order (e.g., per-tenant + per-year counters locked in varying order) is a textbook deadlock generator. Retry logic needs to exist and be idempotent-safe.
  • Backfill hazard. Introducing this against an existing table with populated IDs requires seeding each group's counter to MAX(existing)+1. Get that wrong and you emit duplicates against live data — a data-integrity incident, not a bug.
  • Throughput ceiling. Row-lock serialization caps writes per group. Depending on hardware and transaction length, expect low-thousands/sec per group at best, materially less if the lock is held across a long caller transaction.
  • Metadata anomaly. The listed last release date (2026-03-23) is in the future relative to typical review cadence, and the opportunity score of 38.55 signals a crowded, low-differentiation market. Both warrant a look at the actual tag history before committing.

Key questions

  1. Is increment isolated in its own transaction or joined to the caller's? Are gaps documented as expected behavior?
  2. Which databases are officially supported and tested in CI? Is SQLite explicitly warned against for production?
  3. Is there a unique constraint on the grouping key, and is the increment a single atomic statement or read-then-write?
  4. Is there deadlock detection with bounded retry?
  5. Does it support reset semantics (daily/monthly/yearly), and how are those keyed?
  6. Bulk/batch generation: one lock acquisition per N numbers, or per number?
  7. What are the Laravel and PHP version constraints, and is L11/L12 supported?
  8. Is there a documented backfill procedure for existing tables?

Integration Approach

Stack fit

Good fit for a standard Laravel monolith or modular monolith on MySQL 8+ or PostgreSQL, PHP 8.1+, where the sequential IDs are user-visible document numbers. Poor fit for multi-region active-active writes (the lock is single-primary), for event/telemetry ingestion at volume, and for any environment where SQLite must remain a supported production driver.

Migration path

  1. Counter seeding is the critical step. For each existing entity and group, initialize the counter to MAX(existing sequence) + 1 inside the same migration or a one-off artisan command, and make it idempotent. Do this before the trait is enabled on any model.
  2. Backfill gaps are a business decision, not a technical one. Decide up front whether historical rows get numbers at all, or whether numbering starts from a cutover date. Legal/finance stakeholders usually have an opinion about invoice numbering continuity.
  3. Roll out behind a flag on a low-risk entity first (support tickets, internal references) before orders or invoices.
  4. Run a concurrency proof before cutover: N parallel workers generating M sequences each, asserting exactly M unique contiguous values and zero duplicates. Repeat on the actual production DB engine and isolation level, not on SQLite.

Compatibility

Pin the package version, and pin the Laravel/PHP matrix in your own CI so an upstream constraint bump cannot silently lock you out of a framework upgrade. Verify behavior on the exact MySQL/PostgreSQL version and isolation level you run in production. If you operate multiple database engines across environments (common in teams with SQLite local dev), add a test that runs the sequence path against the production engine in CI.

Sequencing

Spike (1–2 days) → concurrency proof on target engine (1 day) → single-entity pilot (1 sprint) → seed/backfill runbook written and rehearsed → broader rollout → decommission any ad-hoc MAX(id)+1 or count()+1 code paths, which are the actual bug this package replaces.

Operational Impact

Maintenance

Single maintainer, tiny user base, MIT license. The license is the mitigation: the package is small and forkable, and the core logic is a few dozen lines around a locking read. Budget for the possibility that you own this code within 12–24 months. Do not adopt it in a module where you cannot afford to maintain a fork.

Support

GitHub issues only; no commercial backing, no SLA. Response latency should be assumed to be days-to-weeks. For a dependency on the invoice-numbering path, that means your team is the first responder. Acceptable for an internal tool; needs explicit sign-off if it touches revenue-recognized documents.

Scaling

Throughput is bounded by serialization on the counter row per group. Levers, in order of preference: (a) increase group cardinality so concurrent writers hit distinct rows (tenant, document type, period); (b) shorten the caller's transaction so the lock is held briefly; (c) batch-allocate blocks of numbers per request — fast, but converts a rare gap risk into a routine one; (d) if you genuinely need six-figure writes/sec, this is the wrong pattern — use a DB-native sequence or a distributed ID generator and treat the human-readable number as a derived, separately-assigned attribute.

Failure modes to instrument

  • Lock wait timeouts and deadlock retries — emit metrics, alert on rate, not just on errors.
  • Duplicate sequence values — a unique index on the final formatted value is the backstop; without it, duplicates are discovered by a customer.
  • Counter drift after a database restore — backup/restore of the data table without the sequence table, or vice versa, silently resets or advances counters. Include the sequence table in restore verification.
  • Environment skew — a staging restore that rewinds the counter below production's max will collide on the next promotion.
  • Gaps on rollback — document as expected, and confirm it against any regulatory continuity requirement before go-live.

Ramp-up

Low. The public API is small (a trait, a facade, a config file) and a mid-level Laravel developer is productive in half a day. The part that requires senior review is the concurrency contract: isolation levels, lock duration, transaction boundaries, and the gap-on-rollback decision. Write those four decisions into the ADR before integration, not after the first duplicate invoice.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager