This project is not covered by Drupal’s security advisory policy.
A Search API backend that indexes and searches your content with PostgreSQL and the ParadeDB pg_search extension — real BM25 relevance ranking without running a separate search server such as Solr. Search quality is comparable to a tuned Solr setup — ahead of a stock one in our benchmark — and the feature set covers nearly everything Solr backends are used for. The difference is where your search indexes live: in the same PostgreSQL database as the rest of your Drupal data, so there is one fewer service to install, monitor and pay for.
Why this backend?
Search quality in Drupal has long been a choice between two compromises: the database backend is easy to operate but ranks poorly, and Solr ranks well but is another service to install, secure, monitor and upgrade. ParadeDB's pg_search extension puts a modern, tantivy-based BM25 search engine inside PostgreSQL — the database you already run.
The numbers below are from the BEIR TREC-COVID benchmark — 171,332 real documents, 50 topics, graded by NIST relevance judgments — and the module rows are measured end to end through the module's own indexing and query pipeline, not against the raw engine.
| Engine | NDCG@10 | MRR@10 | P@10 |
|---|---|---|---|
| This module, out of the box | 0.656 | 0.942 | 0.724 |
| This module, one analyzer tweak | 0.690 | 0.935 | 0.768 |
| Solr 9, stock install | 0.497 | 0.764 | 0.566 |
| Solr 9, hand-tuned | 0.683 | 0.915 | 0.760 |
Higher is better; all three metrics score the first page of results against human relevance judgments. NDCG@10 rewards putting the most relevant documents highest, MRR@10 measures how often the very first result is relevant, and P@10 is the fraction of the first ten results that are relevant at all.
The "one analyzer tweak" is nothing exotic: the standard English analyzer with the classic ~175-word Snowball stopword list pasted in as additional stopwords — a few minutes in the analyzer UI, applied by a seconds-long index rebuild with no content reindexing. It removes low-information question words such as what, how and does from documents and queries alike, which is exactly what helps when people type natural-language searches. The flip side is that those words become unsearchable, so the module ships it as a per-site choice rather than a default — sites whose users search for phrases like "how to" may prefer the out-of-the-box behaviour.
Features
- BM25 relevance ranking with query-time field boosts (no reindexing when you change a boost) and per-item boosts.
- Language-aware analysis: stemming and stopword removal for the 20 languages pg_search stems, plus Chinese, Japanese and Korean tokenization (jieba / Lindera). Analyzers are configuration entities with a live token preview, and editing one rebuilds indexes in seconds — with no content reindexing.
- True multilingual indexes: optional per-language columns so one index analyses every site language correctly at the same time.
- Rich query support: the core parse modes plus typo-tolerant keyword matching, approximate phrase matching, and a direct-query mode exposing tantivy's own query syntax (
body:(drupal AND search)). - Facets computed inside the index as aggregations: OR facets, granular numeric facets, missing buckets, and facets on fulltext fields.
- Highlighted excerpts from the index's own snippets, at no measurable query cost.
- Autocomplete (word completions and follow-up words), "did you mean" spellcheck, "more like this", grouping (field collapsing), and seeded random sorting.
- Recency boost processor with two human settings: boost factor and half-life in days.
- Semantic and hybrid search via the bundled Search API ParadeDB Vector submodule: embeddings from any AI module provider, stored durably in pgvector and re-generated only when an item's text actually changes, fused with BM25 by reciprocal-rank fusion.
- Operations built in: a ParadeDB tab on every index with storage statistics, a schema-drift verdict and maintenance actions, plus Drush commands for index statistics, optimizing, and schema verification and repair, so deployments can gate on schema health (the full command list is in the README).
- Score debugging: a field you can add in Views showing each result's raw BM25 score and item boost.
- Drupal CMS recipe included: two commands create the ParadeDB server and move the Drupal CMS content index onto it (see Installation).
What's missing compared to Search API Solr
If you are evaluating this module as a Solr replacement, these are the gaps:
- No spatial search.
locationfields are not stored (they are skipped with a logged warning), and distance filtering/sorting via Search API Location is not available. - No token-level boosts. Solr honours the HTML filter processor's per-tag boosts (
<h1>weighing more than<p>); pg_search binds boosts to fields, not tokens, so these are flattened. The supported alternative is structural: index heading text into its own field and boost that field. - No multisite / federated search. Several Drupal sites cannot share one index the way
search_api_solrallows with site-hash filtering. - No external-document indexing. There is no equivalent of the Solr Document datasource for searching documents pushed into the index by systems other than Drupal.
- No streaming expressions or other Solr-side analytics pipelines.
- No separately scalable search tier. SolrCloud offers replication and sharding of the search service itself; here search capacity and failover are PostgreSQL's — which is also a simplification, since there is no second cluster to operate.
Minor behavioural differences: the grouping options truncate and group_facet are ignored, multi-field grouping groups by field combination rather than per field, and string filters are case-sensitive where Solr field types can fold case (see Limitations for the workaround).
Everything else in Solr's feature set — facets (OR, granular, missing buckets, on fulltext fields), highlighting, autocomplete, spellcheck, "more like this", grouping, random sort, retrieving field values from the index — is implemented.
What you get that Solr doesn't offer
The comparison runs in both directions. This module provides:
- Semantic and hybrid search out of the box. The vector submodule fuses BM25 with embeddings from any AI module provider via reciprocal-rank fusion, including a vector-based "more like this" that costs no API call per search. With Solr you would assemble this from additional modules.
- Embedding cost management. Embeddings are stored durably and keyed by content hash, so they are regenerated only when an item's text actually changes — and the index's ParadeDB tab shows embedding spend counters.
- Analyzers editable in the UI, with a live token preview. Saving an analyzer rebuilds the affected indexes in seconds with no content reindexing. With Solr, changing text analysis means regenerating a config-set, deploying it to the server, and reindexing.
- Schema tooling deployments can gate on.
drush search-api-paradedb:schema-diffexits non-zero on drift, andschema-repairrebuilds storage in place without regenerating stored embeddings. - Transactional search. The index is updated in the same database transaction as the content, so search results are never behind the site and cannot get out of sync — there is no commit lag and no separate consistency story.
- One backup, one restore.
pg_dumpcarries the search index together with the site data; a Solr index lives outside your backup regime and is typically rebuilt by reindexing after a restore. - One service to secure, monitor and upgrade — no Java process, no config-set deployment pipeline, no second cluster.
Semantic and hybrid search: the vector submodule
The package bundles a second module, Search API ParadeDB Vector (search_api_paradedb_vector), which adds semantic and hybrid search on top of the keyword backend. It is optional — keyword search needs none of it — and it is configuration, not code: enable the Vector and hybrid search (ParadeDB) processor on an index and pick an embeddings model (or follow the site default from the AI module settings).
- Indexing never waits for an embeddings API. Items are embedded asynchronously through a cron queue; the vectors are stored in a pgvector table with an HNSW index per model. Embeddings are keyed by content hash, so an item is only re-embedded when its text actually changes — routine reindexing and
schema-repairreuse the stored vectors. - Hybrid search fuses the BM25 ranking and the vector ranking by reciprocal-rank fusion, with the fusion constant k and the candidate window configurable on the processor. Each hybrid search embeds the typed keys — one embeddings API call per search — and if the provider is down or rate-limited, the search degrades to plain BM25 instead of failing.
- Vector "more like this" reuses the stored embedding of the source item, so related-content blocks cost no API call per search.
- Cost visibility and model lifecycle. The index's ParadeDB tab shows embedding spend counters. Switching to a different model starts a new embedding set while the old one keeps its storage;
drush search-api-paradedb:vector-models INDEX --purgelists stored models and removes retired ones. - Any model size. Above pgvector's 2000-dimension HNSW limit, storage switches to half-precision vectors (
halfvec) automatically.
One current limitation: facets and spellcheck over a hybrid search count the BM25-matched set only (also noted under Limitations).
Requirements
- PostgreSQL 15 or newer with the
pg_searchextension, version 0.25.2 or newer, on the database server Drupal uses (or on a separate PostgreSQL connection configured insettings.php). PostgreSQL 15+ is what current pg_search releases support; the benchmark above ran on PostgreSQL 18. - Drupal 11, Search API 1.x.
- For semantic and hybrid search (the vector submodule): the pgvector extension, plus the AI module with a configured embeddings provider. In practice pgvector is already there: since version 0.25.0,
pg_searchitself depends on pgvector and cannot be created without it, so any database meeting thepg_searchrequirement above also has pgvector. The status report flags it if it is somehow missing.
The status report checks the requirements and says exactly what is missing.
Installation and migration
- Install the
pg_searchextension on the PostgreSQL server Drupal uses, and create it in the database:CREATE EXTENSION pg_search CASCADE;(theCASCADEalso creates the pgvector extensionpg_searchdepends on). - Install the module:
composer require drupal/search_api_paradedb, then enable it. The status report checks the extension and its version and says exactly what is missing. - Create a ParadeDB server (Configuration → Search and metadata → Search API → Add server), edit each index to move it onto that server, and reindex (
drush search-api:index). Index configuration — fields, processors, view modes, Views — carries over unchanged.
On Drupal CMS, the bundled recipe does step 3 in one go: it applies the stock search recipe, creates the ParadeDB server, and moves the content index onto it:
cp -r web/modules/custom/search_api_paradedb/recipes/drupal_cms_search_paradedb recipes/
drush recipe recipes/drupal_cms_search_paradedb
Migrating from search_api_db or search_api_solr needs no other mechanics, but check the behavioural differences while you are at it: string filters are case-sensitive (see Limitations), token-level boosts are flattened, and location fields are skipped (see the Solr comparison above). Field types the backend cannot store are skipped with a logged warning, never fatal.
Limitations
stringfield filters are case-sensitive and string sorts are byte-ordered (this is what keeps queries inside the index). Index a normalized value if you need folded matching.- Facets and spellcheck over a hybrid (vector-fused) search count the BM25-matched set only.
Spatial search is also missing; that gap is described in the Solr comparison above.
Similar modules
- Database Search (
search_api_db, part of Search API) — works on any database with zero extra infrastructure, but ranks with simple term frequencies. Choose Search API ParadeDB over it when relevance quality matters and you control your PostgreSQL server. - Search API Solr — the most feature-complete backend, and the right choice when you need spatial search or your hosting provides managed Solr. Choose Search API ParadeDB over it to get comparable relevance — in our benchmark: well ahead of a stock Solr install out of the box, and ahead of a hand-tuned one after a one-line analyzer tweak — without operating a second service.
Project information
- Project categories: Integrations, Site search
- Ecosystem: Search API
- Created by daffie on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
