wotz/laravel-online-scope
A lightweight Laravel package that adds an online scope to your Eloquent models, making it simple to query users who are currently online. Track activity with minimal setup and filter results cleanly in your queries.
Architecture fit
wotz/laravel-online-scope is an Eloquent concern, not a subsystem. It almost certainly ships a trait or a scopeOnline() local scope that constrains a model query to rows whose presence column (typically last_seen, last_activity, or last_active_at) falls inside a recency window. That places it squarely in the model/persistence layer with no service-provider wiring, no queue worker, no cache dependency, and no schema ownership. It composes with anything already querying the same table — dashboards, admin filters, whereHas relations — which is the main reason it is attractive: it standardizes a predicate that is otherwise copy-pasted across a codebase with subtly different TTLs.
Integration feasibility
High and cheap. composer require plus one use statement on the model, with configuration likely limited to the column name and the TTL. The realistic integration cost is measured in hours, not sprints. The real work is not the install — it is confirming the package matches your existing presence data semantics and that your timestamp column is indexed.
Technical risk
now() is a DST and UTC-storage bug waiting to happen. This is the single most likely source of silent, hard-to-reproduce defects.scopeOnline on a model, the trait either silently loses or produces a fatal method redeclaration depending on how it is written.users table without a btree index on the presence column, it is a full scan disguised as a one-liner.Key questions
composer.json, and is the constraint a caret range or pinned?now() in app timezone or UTC, and is that documented?offline / notOnline scope for the complement case, or will we write it anyway?Stack fit Fits any Laravel application that already persists a last-activity timestamp — session-authenticated monoliths, modular monoliths, admin panels, and internal tools. It does not fit stateless API services, event-driven architectures where presence lives in Redis or a presence channel, or systems where "online" is a first-class domain concept backed by its own table. The stack-fit question is really: do we already have the column, and do we already agree on what it means?
Migration path
Because the abstraction is a single query predicate, adopt it behind a seam. Introduce an isOnline() / scopeOnline() contract on a base repository or a small domain trait and have that delegate to the package. If the package is later abandoned, vendored, or replaced with first-party code, the swap touches one file rather than every call site. This also lets you run the package and the hand-rolled predicate in parallel for a release cycle and diff the results — the cheapest possible correctness check given there are no dependents to learn from.
Compatibility
Verify the declared Laravel constraint against the framework version actually pinned in composer.lock, not the version in the README. Check interaction with SoftDeletes (global scopes can mask the presence filter), withCount, eager loading, and pagination, since scopes that inject where clauses on joins can produce surprising counts. Confirm it does not register a global scope — a global presence filter on the User model would be a severe and silent behavioral change.
Sequencing
app/Support/ or an internal package is a credible and probably preferable outcome. The license permits it.Maintenance Surface area is tiny, which is the saving grace: a package this small can be audited in an hour and forked in an afternoon. The maintenance burden is therefore low in engineering hours but non-zero in attention — someone must watch for Laravel major-version breaks, and with zero dependents there is no crowd to notice first. Recommend vendoring the logic and dropping the Packagist dependency once the behavior is characterized, unless the author demonstrates an active release cadence.
Support No community to lean on. StackOverflow will not have answers; there is no maintainer SLA. The escalation path is "read the source," which works here only because the source is short. That must be documented internally so the next engineer does not spend a day discovering it. Assign a named owner for the fork or the dependency — this package will otherwise become orphaned code inside the app.
Scaling
The query shape (WHERE presence_ts >= ?) is index-friendly and scales well with a btree index on the timestamp column. The failure mode is not the predicate but its placement: applying it to a large user table inside a paginated list endpoint, or combining it with an ORDER BY on an unindexed column, produces sorts over large row sets. Online-count metrics should be computed once and cached with a short TTL rather than recomputed per request via the scope. Under high write volume on the presence column, expect index churn — consider a coarser bucket or a covering index if the table is hot.
Failure modes
now() produce users who appear offline during business hours. Highest-probability defect, hardest to notice in code review.scopeOnline produces either a fatal error at boot (loud, fine) or a silently shadowed scope (quiet, bad).Builder or Carbon silently alter comparison semantics with no maintainer to patch it.Ramp-up Roughly one hour for any Laravel-proficient engineer to install, read, and apply. The organizational ramp-up is the larger cost: the team needs a shared written definition of "online" and an owner for the code, whether vendored or depended upon. Budget the definition work, not the integration work.
How can I help you explore Laravel packages today?