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

Registry Laravel Package

torann/registry

Torann/Registry is a simple Laravel package for storing persistent key-value settings in the database with cache support. Use a clean registry API to get, set, and manage site-wide configuration values without extra boilerplate.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

The package is a thin key/value store bolted onto standard Laravel scaffolding: one service provider, one facade, a get/set/has/forget contract, a config file, and a migration for a single registry table. That is a very small architectural surface area — it does not introduce a new runtime, a queue dependency, an event bus, or an external service. For a TPM, this is the favorable case: the integration is additive and reversible, and the blast radius of adopting or abandoning it is bounded to the call sites that use it.

The important architectural judgment is not whether the package's internals are good. It is that the package occupies the "runtime-editable configuration" slot in the system, and that slot has well-understood downstream consumers: admin UI, release process, support rotation, and eventually feature-flagging and multi-tenancy. The package itself does not solve those; it only makes the storage trivially available. Treat it as a primitive, not a platform.

The dot-notation key scheme with nested/array value support is sufficient for the realistic near-term inventory: banners, maintenance toggles, upload limits, onboarding copy arrays, default locale, pricing display rules. It is not sufficient for per-user targeting, percentage ramps, or audience segmentation — and it should not be asked to be. The moment those requirements appear, the correct move is to graduate to Laravel Pennant or an equivalent, not to extend this package.

The one genuine architectural concern is the in-memory cache layer combined with multi-node deployments. This is the only place where the package's design shapes your infrastructure decisions rather than the other way around. See "Technical risk" below.

Integration feasibility

Feasibility is high and the ramp is short. The documented path is three commands (composer require, vendor:publish, migrate), the provider auto-discovers on Laravel 5.5+, and the facade and registry() helper resolve without touching config/app.php. Any Laravel developer on the team can complete the first read/write inside an hour. The realistic engineering cost is not the install — it is the wrapper and the discipline around it, which is roughly one to two days including the typed accessor, key registry, seeder, and audit hook.

The single highest-leverage sequencing decision is to build the internal Settings wrapper before the second call site exists, bind it to an interface, and forbid the facade from being imported anywhere else. This is not ceremony. It converts a third-party dependency into a one-file replacement seam, gives you a place to enforce types and tenant prefixes, and makes the eventual migration to spatie/laravel-settings or Pennant a refactor rather than a hunt. A TPM should treat "wrapper landed and adopted as the only access path" as the actual acceptance criterion for the integration, not "package installed."

Technical risk

  • Dependency health is unverified and thin. Zero stars, zero dependents, an unrated score. There is no community maintenance signal to lean on. The realistic planning assumption is that the team owns this code, including the possibility of forking it into the repo. Frame this to stakeholders honestly: this is closer to vendoring a small library than adopting an ecosystem standard. The mitigating fact is that the entire surface is small enough to read in an afternoon, which materially caps the downside.
  • Laravel/PHP compatibility is an assumption, not a fact. No matrix is published for current versions. This must be gated by an explicit spike on the actual target version: publish, migrate, one set, one get, one cache clear, and a scan of logs for PHP 8.2+ deprecation noise. Do not let this be inferred from "it's a Laravel package."
  • Multi-node cache coherence is the top production failure mode. If the driver caches on write, sibling nodes behind a load balancer can serve stale values indefinitely. This will never surface in a single-container dev environment. The decision required is explicit: shared cache store (Redis) for all nodes, or a short TTL with an accepted staleness window, or writes restricted to a single admin process. A TPM should require a two-container staging verification before sign-off.
  • Type drift is silent. Serialization has no schema. A string "25" written where an integer was expected fails comparisons quietly. Mitigation is entirely on your side: typed accessors in the wrapper plus validation against a key registry at the write path.
  • Boot-time reads are a latent availability risk. Reading the registry from a service provider, config loader, route file, or middleware constructor converts a database or cache blip into a full application boot failure. This should be a written, enforced rule, not a code-review preference.
  • Secrets must never land here. Values are plaintext, dumped by every mysqldump, and visible in any admin UI built over them. This belongs in the engineering standard alongside the wrapper rule, because the failure is a security incident, not a bug.
  • Driver choice is a trap for the unwary. memory is per-request and resets (tests only), json writes to the local filesystem and silently diverges across containers and breaks on read-only filesystems. Neither belongs in production. database plus a cache is the only sensible default.

Key questions to resolve before committing

  1. What is the concrete inventory of settings we intend to move, and does any of it involve per-user, per-tenant beyond simple key-prefixing, or percentage-based targeting? If yes to targeting, this is the wrong tool.
  2. What is our deployment topology at launch — single node or multiple? Which cache store is shared across all nodes? This determines whether the coherence risk is real or theoretical.
  3. Who is the on-call owner when a bad setting is written at 3am, and what is the rollback path? (Answer: without an audit trail and a key allow-list, the answer is "nobody knows.")
  4. Do we accept upstream maintenance risk, or do we pre-commit to forking into the repo? Decide now; deciding later under incident pressure is worse.
  5. What is the graduation trigger to Pennant or spatie/laravel-settings? Write the numeric or event-based threshold (e.g., flag count, first targeting requirement, first audit requirement from a customer) before adoption, not after.

Integration Approach

Stack fit

The fit is good and deliberately shallow. It is a conventional Laravel package: service provider, facade, publishable config, publishable migration. It integrates with the same cache and database layers the application already operates and does not require a new vendor, a new runtime, or new infrastructure. For a team already on Eloquent plus a cache store, the mental model is one sentence: "a key/value table with a cache in front."

The one stack-level constraint to state plainly is that this is not a configuration replacement. Laravel's config/*.php files remain the source of truth for anything that is structural, environment-dependent, or needed at boot. The registry is for values that must change without a deploy — the overlap set is small and should be defined in the key registry, not discovered by accident.

Migration path

The migration is additive and low-drama, but two details deserve attention before the first production migrate:

  • Inspect the published migration rather than trusting it. Check the key column length and whether the key is indexed and unique. A 64-character varchar with a unique index is a wall you hit when keys grow a tenant prefix. Changing this before the first production migrate is a two-minute edit; after, it is a schema migration with downtime risk.
  • Anticipate columns you will want and don't have. There is no type column, no tenant column, no updated_by. You can either add them at adopt time or accept that per-tenant scoping is done by key prefixing. Prefixing is the documented approach and is fine, but committing to it now avoids a data migration later.

Compatibility

Verify the matrix yourself on the target Laravel and PHP versions — pin the version in composer.json, run publish/migrate/set/get/cache-clear, and check logs for deprecations. Treat a clean spike as a hard gate on the adoption decision. If the spike fails, the fallback (fork into the repo) is cheap precisely because the surface is small; budget for it as a plausible outcome rather than a disaster.

Testing compatibility is part of this: swapping REGISTRY_DRIVER=memory in phpunit.xml makes the registry an in-process array with no database, no teardown, and no ordering surprises. Tests should assert against the Settings interface, never the facade, so they survive a backend swap or an outright replacement.

Sequencing

  1. Spike (half a day). Install on the target versions, publish, migrate, round-trip every value type (bool, int, float, array, null), clear cache, scan logs. Gate on this.
  2. Wrapper + interface + key registry (one to two days). App\Support\Settings with typed accessors, bound to an interface, plus config/settings.php enumerating every legal key with type and default. Add the audit hook now — an actor/key/old/new log line or table — because retrofitting it after writes are in the wild means losing the history you actually wanted.
  3. Defaults seeder. Re-runnable, has()-guarded, so fresh installs, CI, and tests are deterministic and match production shape.
  4. First use case — read-mostly and boring. A support banner or maintenance message. Read on every page, written monthly, tolerable staleness.
  5. Two-container staging coherence test. Write on node A, read on node B, confirm the chosen cache strategy holds. Do not skip this because "it works locally."
  6. Admin surface + write validation. Form request validating against config/settings.php before set() is reachable.
  7. Second and third use cases. Feature gating (with the staging-area rule) and per-tenant prefixing via the wrapper — before tenants exist in the wild, since retrofitting prefixes is a data migration.
  8. Graduation review. Compare observed usage against the pre-agreed triggers.

The ordering is deliberately: gate compatibility, establish the seam, make it deterministic, prove it in production topology, and only then expand scope. Expanding call sites before the wrapper exists is the failure mode that turns a two-day integration into a permanent undocumented dependency.

Operational Impact

Maintenance

Ownership effectively transfers to your team. With no stars and no dependents, there is no meaningful upstream maintenance signal, and the responsible planning assumption is that you maintain it — including patching it for future Laravel/PHP releases or forking it into the repo. The saving grace is the size: a provider, a facade, a driver, a migration, and a small config file. Maintenance cost is best modeled as "a small internal library we happened to source externally," not "a vendor relationship."

Two recurring maintenance chores should be scheduled, not hoped for:

  • Orphan sweep, quarterly. Diff SELECT key FROM registry against config/settings.php and delete unreferenced keys. Without this, deleted features leave keys behind forever and the table becomes archaeology.
  • Flag hygiene review. Any registry-backed feature flag older than one or two releases either graduates to Pennant or is deleted. Without this written rule, you have an unmanaged flag swamp within a quarter — this is a near-certainty, not a risk.

Support

Support load splits into two distinct buckets with different owners.

Operator support (the common case) is answering "who changed this and can we change it back." Without an audit trail, that question is a five-minute answer or an incident review, and the package provides nothing. Build the audit hook in the wrapper at integration time; it is an hour of work and it converts the most frequent support request from archaeology into a lookup. The admin surface also needs a visible "last modified by / when" for the same reason.

Engineering support is debugging "the value is wrong." The layered diagnostic is fast and should be documented for the team: check what is actually stored (Registry::all() or a direct table read) → if storage is right and reads are wrong, it is the cache → if storage is wrong, it is the write path or serialization. php artisan tinker against the facade beats adding logging. Also document the cache-clear gotcha: php artisan config:clear does not clear the registry's own cache; you must flush the registry cache key or forget() and re-set. This will otherwise burn an hour of someone's afternoon.

Scaling

Scaling behavior splits cleanly along read/write lines.

Reads scale well. In-memory caching means repeated access within a request does not hit the backend, so the registry is effectively free at read time even on hot pages — provided you follow the view-composer pattern rather than calling the facade inside a loop in a template.

Writes do not need to scale, and should not be asked to. This is a low-write store by design. If write volume is high, the design is wrong — you want a different system.

Topology is the real scaling constraint. Multi-node deployment plus invalidate-on-write caching produces stale reads on sibling nodes. The options, in order of preference: a shared cache store (Redis) all nodes read from; a short TTL with an explicitly accepted staleness window; or writes restricted to a single admin process. Whichever you pick, it is a decision that must be made consciously and verified in staging with two app containers, because a single-node dev environment will never surface it. This is the one operational risk that scales with the business rather than staying fixed.

Key-space scaling has a ceiling worth naming: the key column length and uniqueness constraint. Tenant prefixing consumes characters fast. Decide the key naming convention (domain.subject.setting, flat) and enforce it through the key registry rather than trusting convention, and validate key length at the write path so you fail loudly instead of truncating silently.

Failure modes

Ordered by expected frequency and severity:

  • Stale reads across nodes. Most likely in production, invisible in dev, and produces "the setting didn't take" reports that erode trust in the admin surface. Mitigation: shared cache store, verified in staging.
  • Boot-time read causing total outage. A database or cache blip becomes an application boot failure rather than a degraded feature. This is the highest-severity mode and is entirely self-inflicted. Mitigation: hard rule — never read the registry during boot, from providers, config loaders, route files, or middleware constructors; resolve lazily or via a view composer.
  • Silent type drift. set('limits.uploads.mb', '25') writes a string; a comparison elsewhere fails with no error. Mitigation: typed accessors in the wrapper, write validation against the key registry, and an explicit round-trip test of every value type whenever serialization or the column type changes.
  • null vs. absent ambiguity. get($key, $default) returns the default both when the row is missing and when the stored value is null. If storing null is a legitimate state, use a sentinel or check has() first. Document this — it surprises people.
  • Nondeterministic fresh environments. An empty table means every get() falls through to whatever default the call site happened to pass, so staging, CI, and production silently diverge. Mitigation: the defaults seeder, run in every environment.
  • Secrets leakage. Plaintext values, dumped by every backup, visible in the admin UI. Mitigation: written standard that credentials live in .env or a secrets manager, reinforced at code review.
  • Driver misuse. memory in production means settings vanish per request; json in a containerized deployment means silent divergence and failures on read-only filesystems. Mitigation: pin the driver in config and prohibit the other two outside tests.
  • Package abandonment. Upstream goes quiet and a future Laravel release breaks it. Severity is low because the fork cost is an afternoon. Mitigation: pin the version, and keep the wrapper as the only import point so the swap is one file.

Ramp-up

Ramp-up is short and does not require specialist knowledge, which is a real advantage for a small team. A Laravel-fluent developer is productive in under an hour and fully conversant with the wrapper, key registry, and diagnostics in a day. The cost is not learning the API — it is absorbing the operational rules, and those need to be written down rather than transmitted orally.

The onboarding artifact should be a short internal standard covering, at minimum: the wrapper is the only access path; never read during boot; typed accessors only, never raw get() at call sites; secrets never go here; flags are staging-only and expire; default to database plus shared cache; check storage → cache → write path in that order when debugging; and the cache-clear gotcha. Six bullets and a paragraph. Without it, the rules live in one engineer's head and decay the moment they change teams.

For the TPM specifically, the ramp-up framing to stakeholders is: this is a small, contained capability that removes a class of change requests from the release pipeline — support copy, banners, limits, onboarding text, early-stage flags, and pre-billing tier differentiation. The measurable outcomes to track are release-cadence relief (fewer config-only deploys), reduction in "can you change this string" interrupts, and time-to-change on runtime settings. The strategic value is as a probe: real usage generates the actual requirements — audit, typing, targeting, secret handling, percentage ramps — that tell you precisely when to graduate to spatie/laravel-settings, Pennant, or a flag platform. Adopt it deliberately, with the graduation threshold written before adoption, and the decision to eventually leave it becomes evidence-based rather than a matter of taste.

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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox