appstract/laravel-options
Store and retrieve global key-value options in Laravel with a simple option() helper and Options facade. Values persist in a database table, support caching for fast access, and can be easily typed, making site-wide settings manageable without touching config files.
Architecture fit. appstract/laravel-options is a thin, DB-backed global key-value store exposed through a facade and helper (e.g. Option::get()/set()), with a published options table and cache-backed reads. It fits cleanly in a Laravel monolith or modular monolith as an operator-controlled settings layer: feature toggles, maintenance banners, throttle thresholds, integration IDs, business copy that product wants to change without a deploy. It does not fit as a general data store, per-user preferences, tenant-scoped configuration, or a substitute for config/, a queue, or a cache. The key architectural decision is whether we are adopting a settings mechanism (low risk) or a runtime configuration bus (higher risk, needs governance).
Integration feasibility. Low. One Composer require, publish + run migration, optional config publish. No external services, no queue workers, no sidecar. A competent Laravel developer can integrate and wrap it in a day. The real effort is not installation but the wrapper and governance around it — the package intentionally exposes a very permissive global API.
Technical risk.
config:cache enabled; stale settings after deploy are the most likely incident class.Key questions for the team.
Stack fit. Fits any single Laravel application with Eloquent and a shared cache store. It does not give non-Laravel services access; if we run multiple services, expose settings via an internal API rather than having each service read the DB directly. Multi-region deployments should treat the settings table as single-writer.
Migration path.
SettingsRepository interface and adapter; forbid direct facade use outside it. This is the single most valuable step — it gives us swap-out, logging, typing, and fallback in one place.config/ and .env. Do not bulk-migrate configuration.Compatibility. Pin the exact version in composer.json; verify PHP/Laravel constraints, the migration's column type (JSON vs. text) against MySQL/Postgres, and behavior under SQLite for tests. Confirm the facade is fakeable/stubbable for unit tests, or wrap it so tests can stub the repository instead.
Sequencing.
Maintenance. Very low code surface; the cost is ownership. Budget a quarterly check of upstream releases and Laravel major-upgrade compatibility, plus a documented fork trigger (e.g. no release for 12 months or a blocking incompatibility). Keep our wrapper thin so a fork or replacement is a contained change.
Support. The operational question is who can change production behavior, and how we know who changed it. The package gives no audit trail, so the wrapper should log key, old value, new value, actor, and request ID. Provide exactly one sanctioned write path (artisan command or admin screen); the Option::set() facade should not be reachable from arbitrary application code.
Scaling. Reads are cheap with a warm cache; writes are single-row updates. This scales fine for tens to low hundreds of keys updated occasionally. It does not scale as a write-heavy store, a job/queue table, or a per-request mutable registry. Keep key cardinality bounded — table growth is a symptom of misuse, not a feature.
Failure modes.
Ramp-up. A mid-level Laravel developer needs roughly half a day to understand the package and one to two days to integrate safely through the wrapper and document it. Organizational ramp-up is the larger cost: teams need the rule that this store is for global, operator-controlled, non-sensitive configuration, and that anything typed, scoped, audited, or secret belongs elsewhere.
How can I help you explore Laravel packages today?