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

Postgres Search Bundle Laravel Package

shopsys/postgres-search-bundle

Shopsys Postgres Search Bundle brings native full-text search to Shopsys projects using PostgreSQL, letting you index and query products quickly without running a separate search engine.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Search backend strategy (build vs. buy vs. borrow). Frames the recurring "do we need a dedicated search engine at v1, or can the database we already run do this?" call. PostgreSQL native FTS is the zero-new-infrastructure option: no second datastore, no index pipeline, no vendor contract. The decision this supports is defer the search vendor, not adopt this package — for a Laravel codebase the deliverable is the pattern (tsvector/tsquery + GIN + ts_rank_cd), not a Composer dependency.
  • Scope of the search MVP. Sharpens the line between "search finds a product by name/SKU/description, ranked" (native FTS handles this) and "search needs facets, typo tolerance, synonyms, merchandising pins, A/B-testable relevance" (it does not). This is a roadmap commitment, not a technical footnote: it needs to be written down as deferred scope with a named trigger for revisiting.
  • Cost and headcount avoidance. Every index not stood up is a service not monitored, scaled, backed up, patched, or paid for. Supports a decision to ship functional search in weeks rather than a quarter, and to spend the saved budget on catalog quality or conversion work instead.
  • Consistency as a product promise. Because the search vector lives in the same tables as the entities, writes and index updates share a transaction. That supports product promises external engines buy with effort: sold-out items vanish from results immediately, new SKUs are searchable on publish, no "invisible for N minutes" class of bug. Worth stating explicitly to stakeholders because it is a genuine differentiator at this scope.
  • Market launch sequencing. Postgres text-search configurations are language-specific, and CJK tokenization is out of reach. This constrains which locales can launch with acceptable search and in what order — a launch-planning input, not just an engineering detail.
  • Build-vs-borrow at the dependency layer. The package is itself a fork: Shopsys forked intaro/postgres-search-bundle and added a 0.1 tag only for Composer version management, with 0 stars and 0 dependents. The PM-relevant signal is that upstream is not reliably versioned and nobody is on the hook for defects. That argues for adopting the upstream or owning a thin internal implementation.
  • Where the effort actually goes. For a Laravel stack, the Symfony bundle's wiring (DI extension, console command, Doctrine event subscribers) is unusable — no Scout driver, no Eloquent integration. The reusable asset is a few hundred lines of SQL and query building. The decision is therefore "own a small search layer behind our own interface," which conveniently keeps the exit door to Meilisearch/Elasticsearch open.

When to Consider This Package

Consider the technique (native Postgres FTS with GIN indexes) when all of the following hold:

  • You already run PostgreSQL and have no appetite for a second datastore.
  • Requirements are genuinely keyword-plus-ranking over a handful of text columns, possibly with prefix matching and highlighting.
  • Catalog/content volume is modest — low hundreds of thousands to low millions of rows. Relevance quality and query cost degrade before raw row count does.
  • You can maintain the index with a trigger or generated column rather than application-level listeners; bulk writes, queue jobs, and raw upsert/DB::statement bypass model events in every ecosystem, and that is this design's weakest inherited assumption.
  • You can accept owning the code. No community, no security response, no release cadence — treat any adoption as vendored code.

Consider the package itself only if you are on Symfony with Doctrine ORM and specifically want the entity-mapping and listener integration path, and you have accepted fork maintenance.

Look elsewhere when:

  • You are on Laravel. Realistically you re-implement the ~300 lines of query logic and discard the bundle plumbing. Don't add shopsys/postgres-search-bundle to composer.json and try to boot a Symfony bundle inside Laravel.
  • You need faceted navigation, typo tolerance, synonym management, learning-to-rank, or merchandising/pinning — go to Meilisearch, Typesense, OpenSearch/Elasticsearch, or Algolia.
  • You need many locales at once or CJK tokenization.
  • Search is a product differentiator rather than a utility.
  • You need a supported dependency with SLAs and a release history.
  • Write volume is heavy and you can't commit to autovacuum tuning and GIN index-bloat management.
  • Search load sharing a database with transactional load is unacceptable — there is no isolation between an expensive search query and checkout latency.

Mandatory gates before any commitment: confirm the PostgreSQL floor (websearch_to_tsquery needs 11+), verify unaccent/pg_trgm can be enabled in every environment including managed Postgres you don't control (RDS, Cloud SQL, Supabase), benchmark on a production-shaped dataset, and get a written answer on which upstream commit 0.1 pins to and who patches it when Postgres or Doctrine changes underneath. Prefer upstream intaro/postgres-search-bundle unless the Shopsys tag is specifically needed — otherwise you take on fork maintenance for a versioning convenience.

How to Pitch It (Stakeholders)

To executives: This is a cost-deferral play, not a search strategy. PostgreSQL — which we already run and pay for — can deliver functional, ranked product search out of the box. Pursuing the native-FTS approach lets us ship search without standing up, integrating, and operating a dedicated search service, avoiding the infrastructure spend, the integration work, and the ongoing on-call burden for as long as our needs stay simple. Be explicit about the trade-off: we get keyword search, not relevance engineering. No facets, no typo tolerance, no merchandising rules. We should name the metrics that tell us the deferral has expired — search-exit rate, zero-result rate, conversion lift from search — and budget the migration to a dedicated engine as a known future cost, so it lands as a planned decision rather than a surprise. One caveat worth surfacing: the specific package is an unmaintained fork of an upstream library, so we would be copying the approach and owning a small amount of SQL rather than taking a vendor dependency.

To engineering: For a Laravel codebase this is a pattern source, not a dependency. Take the to_tsvector/websearch_to_tsquery query construction, ts_rank_cd ordering with setweight field weighting, a generated or trigger-maintained search_vector column, and a GIN index created CONCURRENTLY. Leave the Symfony bundle on the shelf — its DI extension, console command, and Doctrine event subscribers are dead weight here, and we'd be pinned to a 0.1 fork with no upgrade story for code we can own outright.

Sequence it so each step is reversible: (1) benchmark native FTS against the current implementation on production-shaped data — this gates the project; (2) introduce a framework-neutral SearchService interface and route existing search through it with current behavior behind it; (3) add the schema and backfill in batches, maintaining vectors via trigger or generated column rather than model events, since bulk and queue writes skip those; (4) shadow-run and diff top-N results against the incumbent; (5) cut over per surface — search page, typeahead, admin — behind a feature flag; (6) keep the old path in reserve for a cycle. Encapsulating behind the interface means swapping to Meilisearch or Elasticsearch later is a contained change rather than a rewrite. Instrument two things from day one: a reconciliation job counting rows whose stored vector disagrees with a recomputed one, and a fixed golden query set asserted in CI to catch silent relevance regressions when dictionary or unaccent configuration changes.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route