These pitfalls tie common symptoms to the mental model that usually causes them, a fix pattern, and the guide that owns the full rule.
How to use this page
Skim the headings for a match to your symptom, read the Wrong model line to sanity-check assumptions, then follow the Authority link for the full rules rather than duplicating them here.
Treating search visibility as “same transaction” as the database
Symptom: A record insert or update succeeds, but Scrypath.search/3 does not return the row you just wrote—or returns stale data—so you assume the library “lost” the document.
Wrong model: Search indexes are updated on a separate path from your Ecto transaction commit; “accepted work” is not the same thing as “searchable right now,” especially with :inline, :oban, or :manual sync.
Fix pattern: Decide which sync mode you run, then read the lifecycle language for that mode before branching application code on search results.
Authority: See Sync modes and visibility for the authoritative semantics.
Treating Meilisearch as the business source of truth
Symptom: A user can find a record in search that should be hidden, deleted, or outside their tenant; or the UI trusts search-hit fields that no longer match the database.
Wrong model: The search document is treated like the authoritative record instead of a denormalized projection.
Fix pattern: Keep sensitive authorization checks in the database path, index only safe display fields, and hydrate records from the repo when visibility matters. Rebuild from source data when projection drift is broad.
Authority: Meilisearch concepts for the projection model, then Drift recovery for repair paths.
Changing filterable or sortable fields after the import
Symptom: A filter or sort option works in the UI code but fails, behaves oddly, or requires a long backend operation after deployment.
Wrong model: Meilisearch settings are treated like harmless display preferences.
Fix pattern: Declare settings in code, apply them before import, and treat index-contract changes as migration/reindex work. Use settings diff and managed reindex instead of patching broad settings casually in production.
Authority: Relevance tuning.
Indexing documents that are too large or too private
Symptom: Search responses are slow or bloated, indexing uses more memory than expected, or fields appear in search results that should have stayed server-only.
Wrong model: The indexed document is a copy of the Ecto struct or rendered page.
Fix pattern: Index a lean search card: stable ID, searchable text, safe display fields, and the filter/sort fields Meilisearch needs. Leave private or frequently-changing business state in Postgres.
Authority: Meilisearch concepts.
Producing one Meilisearch task for every tiny event
Symptom: /tasks shows a growing queue, failed tasks pile up, or search freshness falls behind even though each individual write is small.
Wrong model: Async indexing removes the cost of high-churn updates.
Fix pattern: Batch, debounce, or omit fields that do not affect search quality. Avoid syncing page views, counters, and inventory ticks one record at a time unless the product really needs that freshness.
Authority: Meilisearch operations and Search backend operations.
Rebuilding directly into the live index
Symptom: Users see partial results or empty search during a repair, import, or settings change.
Wrong model: A full rebuild is just a larger backfill.
Fix pattern: Use managed reindex semantics: create a target index, apply settings, backfill it, verify counts and searches, then cut over deliberately. Use cutover?: false when the target needs inspection first.
Authority: Drift recovery and Meilisearch operations.
Federating search_many/2 without reading the multi-index rules
Symptom: {:error, {:invalid_options, _}} (or related option errors) when combining global_schemas, federation weights, or :all expansion—often after copying options from a single-index example.
Wrong model: Treating federation and :all as “just more indexes” instead of a constrained composition with preflight validation.
Fix pattern: Start from the multi-index guide’s rules for allowed combinations, then align options with the documented shapes before retrying.
Authority: Multi-index search.
Expecting search/3 to guess a schema you never declared with use Scrypath
Symptom: {:error, _} paths that mention an unknown or unregistered schema module, or confusion about why a module is “not searchable,” even though Ecto can load the struct.
Wrong model: Any Ecto.Schema is automatically indexed and searchable without the Scrypath declaration layer.
Fix pattern: Ensure the schema uses use Scrypath with the intended fields and that your app registers the index name you pass to search/3.
Authority: Getting started for the configuration mental model, then Sync modes and visibility for how sync attaches to writes.