matchish/laravel-scout-elasticsearch
Elasticsearch driver for Laravel Scout, replacing the default engine with a full-featured Elasticsearch backend. Keep Scout's simple model-based API while gaining fast full-text search, filtering, aggregations, and multi-index queries. Straightforward to configure and scale.
Architecture fit The package is a Scout engine implementation plus an opinionated orchestration layer on top. Two capabilities matter:
elasticsearch driver, translating Scout's Engine contract (update, delete, search, paginate, mapIds) into elasticsearch-php calls. Any model already using Laravel\Scout\Searchable becomes indexable with a config change.Searchable trait and Search facade to query several indices in one logical request and merge results into a single ranked, paginated set. This is what Scout does not do natively and what most teams end up hand-rolling.Architecturally this is a thin, well-scoped adapter. It does not own cluster topology, mapping lifecycle, or relevance tuning — it delegates to Elasticsearch. That is the right boundary, but it means the package is not a search platform; it is a connector with a multi-index query helper.
Integration feasibility Low effort, medium surprise risk.
Searchable trait with a same-named trait from a different namespace, and exposes a static facade rather than an Eloquent query. Teams will have two search idioms in one codebase (Model::search() vs Search::search(A::class, B::class)), and trait-import mistakes will fail silently or confusingly.search:import-style backfill is resumable before assuming production readiness.Technical risk
from + size per index. This interacts with index.max_result_window (10k default) and makes deep pages expensive or impossible. There is no clean search_after story across heterogeneous index schemas. Treat this as a functional ceiling to design around, not a bug to fix.Key questions for the maintainer / spike
max_result_window, and is search_after offered?Stack fit Strong fit for a Laravel monolith on Scout 9/10 with a genuine cross-entity search requirement (e.g., one global search box spanning articles, products, users). Weak fit if you only need single-model search — Scout's Meilisearch/database drivers plus a smaller footprint will cost less. Also a weak fit if your platform standard is OpenSearch and you need vendor-blessed support.
Migration path Treat this as a feature-scoped adoption, not a search-platform replacement.
Searchable, backfill via Scout's import command, keep a fallback to SQL LIKE behind a flag during rollout.Model::search() is sufficient and better understood.Compatibility
Pin matchish/laravel-scout-elasticsearch to an exact version and pin elasticsearch/elasticsearch to the cluster's minor line. Scout majors have changed Engine method signatures historically; a Scout upgrade is a package upgrade is an ES client upgrade — three lockstep dependencies. Add a CI job that boots the package against the target ES image so version skew fails in CI, not in production.
Sequencing
Maintenance Ongoing cost is modest but not zero: dependency bumps ride on Laravel/Scout/ES release trains, and each bump is a potential breaking change across three libraries. Plan ~0.1–0.2 FTE steady-state plus an explicit fork readiness decision — clone, pin, and verify you can build and patch it internally. With 0 dependents and a small maintainer set, "we can fork it" must be a rehearsed capability, not an assumption. Allocate maintenance to a named owner; unowned search connectors rot quietly.
Support Community-only: GitHub issues, MIT with no warranty, no commercial escalation. Internal runbooks are a deliverable, not a nice-to-have. The bespoke multi-model API is documented at README depth, so tribal knowledge will accumulate — write it down or it leaves with the engineer.
Scaling Cluster sizing is dominated by Elasticsearch, not this package — shard count, heap, and refresh interval are your levers. What the package adds to the cost curve:
max_result_window and the absence of a cross-index cursor means you should design the UX to cap page depth (e.g., 10 pages) rather than promise exhaustive pagination.Failure modes and mitigations
| Failure | Symptom | Mitigation |
|---|---|---|
| Cluster unavailable | Search endpoints 500 | Fallback path (DB query or cached results) behind a circuit breaker |
| Index drift / lost queue jobs | Stale or missing results, no error | Periodic reconciliation job (count + checksum per index), alert on delta |
| Mapping change without alias swap | Reindex requires downtime or data loss | Alias-per-index convention established before first production index |
| ES client / cluster version skew | Runtime errors on upgrade day | CI boots against target ES image; exact version pins |
| Over-fetch memory blowup | Timeouts on deep pages | Hard page-depth cap at the API layer |
| Trait/namespace confusion | Model::search() and multi-model path diverge in behaviour |
Code review rule + static analysis; single documented search entry point per surface |
Ramp-up For a competent Laravel engineer: roughly one day to working single-model search, one week to a trustworthy pilot including mapping design, relevance sanity checks, and the alias/reindex runbook. The learning curve is not the package's API — it is Elasticsearch itself (mappings, analyzers, relevance) plus the package's non-Scout-shaped multi-model semantics. Budget the second part; it is where surprises live.
TPM verdict
Worth a spike, gated on the ES 8 / Scout compatibility answers. The value proposition — multi-model search without hand-rolling _msearch merging — is real and commonly needed. The risks are entirely conventional for a small MIT connector: version coupling, a thin maintainer base, and a bespoke API that diverges from Scout's. None are disqualifying for a feature-scoped pilot with a fallback path, an alias strategy from day one, and a rehearsed fork plan. Do not adopt it as the foundation of a company-wide search platform.
How can I help you explore Laravel packages today?