L’interface est localisée ; les présentations et documents des Skills sont traduits automatiquement par IA dans votre langue. Le code, les commandes, chemins et termes techniques restent en version originale, et le document de l’auteur fait foi.
Use this skill when designing search functionality, indexing strategies, or relevance tuning. This skill enforces: derived index from source of truth, index aliases for zero-downtime reindex, proper field mapping with analyzers, and resource limits. Applies to Elasticsearch, Meilisearch, Algolia, or any search engine. Do NOT use for: primary database querie…
Independent GitHub snapshot · Automated classification · Original documentation governs
name: backend-search-patterns
description: >
Use this skill when designing search functionality, indexing strategies, or relevance tuning. This skill enforces: derived index from source of truth, index aliases for zero-downtime reindex, proper field mapping with analyzers, and resource limits. Applies to Elasticsearch, Meilisearch, Algolia, or any search engine. Do NOT use for: primary database queries, simple LIKE/ILIKE lookups, or full-text search in application DB.
version: "2.0.0"
author: "j4flmao"
license: "MIT"
compatibility:
claude-code: true
cursor: true
codex: true
windsurf: true
tags: [backend, search, phase-6, universal]
Backend Search Patterns
Purpose
Design search architecture with indexing strategy, query design, and relevance tuning.
What kind of search do you need?
├── Complex search: aggregations, geo, custom scoring, multi-language
│ └── Elasticsearch / OpenSearch — full control, steep learning curve
├── Simple typo-tolerant full-text search, instant setup
│ └── Meilisearch — excellent out-of-box relevance, minimal config
├── Managed, no ops, global edge network, per-query pricing
│ └── Algolia — fastest time-to-value for e-commerce and content
├── Fast, simpler alternative to Elasticsearch, lower resource usage
│ └── Typesense — REST-first, good relevance, low memory footprint
└── Already using AWS ecosystem, simple search needs
└── OpenSearch Service — managed, familiar if coming from ES 6.x
How to Index?
How fresh does search data need to be?
├── Real-time (seconds), high throughput
│ └── CDC (Debezium) → Kafka → search consumer
├── Near real-time (seconds-minutes), moderate throughput
│ └── Webhook / event-driven index updates
├── Near real-time, strong consistency (read-your-writes)
│ └── Dual-write: DB + search in same operation (with outbox pattern)
├── Batch (hours-days), small dataset, infrequent changes
│ └── Periodic full reindex — truncate and retransform all data
└── I don't know yet
└── Start with batch reindex daily. Add CDC when freshness requirement emerges
Workflow
Step 1: Search Provider Selection
Provider
Type
Hosting
Query Complexity
Relevance
Performance
Cost
Elasticsearch
Self-managed/SaaS
Cloud/on-prem
Full DSL
Custom BM25
High
Infra cost
OpenSearch
Self-managed/SaaS
Cloud/on-prem
Full DSL
Custom BM25
High
Infra cost
Meilisearch
Self-managed/SaaS
Cloud/on-prem
Simple REST
High OOTB
Very high
Open source
Typesense
Self-managed/SaaS
Cloud/on-prem
Simple REST
High OOTB
Very high
Open source
Algolia
SaaS
Managed
Simple REST
Very high OOTB
Edge-cached
Per search op
Elasticsearch for complex search with aggregations, geo, custom scoring. Meilisearch for simple typo-tolerant search, instant setup. Algolia for managed high relevance out-of-box, global CDN, no ops. Typesense as a faster simpler alternative to Elasticsearch. OpenSearch as the open-source fork of Elasticsearch (after license change).
Step 2: Index Mapping
Define every field with explicit type: keyword for exact match/filtering/sorting, text with analyzer for full-text, integer/float/date for range queries, geo_point for geo-spatial, boolean for flags. Set language-specific analyzers per field. Use doc_values: true on fields used for aggregations and sorting (critical for performance). nested type for arrays of objects (maintains document boundaries). enabled: false on fields not searched (saves index space).
CDC: Debezium captures DB changes, emits to Kafka, consumer updates search index. Bulk: periodic batch job reads all data, truncates index, rebulks. Webhook: app emits events on data change, consumer updates index. Dual-write: app writes to both DB and search in same transaction. Queue-based: app enqueues index event, consumer processes.
Step 4: Search Query DSL
Full-text: match and multi_match with field boosting (title^3, description^2). Filters: term/terms for exact, range for numeric/date, geo_distance for geo, exists for field presence. Faceted: terms aggregation with size limit, range aggregation for price buckets, nested aggregations for drill-down. Autocomplete: match_phrase_prefix or edge-ngram analyzer + completion suggester. Post-filters: apply after aggregation calculation (filter UI without affecting facet counts).
BM25 parameters: k1 (1.2 default) controls term frequency saturation — increase to 2.0 for long descriptions, decrease to 0.5 for short titles. b (0.75 default) controls length normalization — decrease to 0.3 for uniform-length fields. Field boosting: title^5, description^2, tags^1.5. Function scoring: recency (Gaussian on date), popularity (field_value_factor), personalization (script score for user history). Synonyms: configure as analyzer filter for query expansion. Rescore: run expensive scoring on top-100 results only.
Always use aliases for production reads/writes. Reindex: create new index with updated mappings → bulk load data → atomically swap alias from old to new → delete old index. Write alias points to index accepting writes. Read alias points to index serving queries.