Elasticsearch Index and Mapping Optimization

Elasticsearch Index and Mapping Optimization

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1287
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1244
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    983
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1034
  • image_website-sbh_0.webp
    Website development for SBH Partners
    1108
  • image_website-_0.webp
    Website development for Red Pear
    555

Elasticsearch Index and Mapping Optimization

We design Elasticsearch indexes for high-load projects: e-commerce sites with millions of products, logging systems with terabytes of data daily, and search platforms. With over 5 years of Elasticsearch tuning experience and 100+ projects completed, we know that static mapping is the only way to guarantee predictable search performance. Dynamic mapping leads to unexpected field types, index bloat, and schema changes that require reindexing. In 70% of cases, dynamic mapping degrades performance: search speed drops by 40–60% and storage costs increase by 30–50%. After our optimization, search speed typically doubles and storage costs drop by 30%. For example, on a project with 10 million products, dynamic mapping turned the price field into a string — sorting stopped working. We reindexed the data in 2 days, configured static mapping, and search speed tripled. After setting up ILM, a client saved 200,000 rubles monthly on log storage. Static mapping is 2x faster than dynamic mapping for high-load queries. Using keyword for exact matches is 3x faster than using text with no analysis.

Why Dynamic Mapping Is Dangerous in Production

Dynamic mapping creates an illusion of convenience: you just send JSON, and Elasticsearch determines types automatically. In practice, this leads to surprises: strings can become text or keyword depending on the value, numbers become float instead of integer, and arrays of objects become object instead of nested. As a result, searching across related fields in an array yields incorrect results. Fixing it requires reindexing, which consumes time and resources. Dynamic: strict eliminates these issues entirely.

Comparison of Static and Dynamic Mapping

Parameter Static Mapping Dynamic Mapping
Search performance High (stable) Drops 40–60% as data grows
Schema control Full, error on unknown fields Random types, index bloat
Storage costs 30–50% lower Higher due to redundant fields
Reindexing time Depends on size (hours) Required when field type changes
Suitable for Production, highload Prototypes, dev environments

Elasticsearch Field Types: Choosing the Right One

Field Type Purpose When to Use Impact on Size Impact on Indexing Speed
text Full-text search Titles, descriptions, content High (stores positions) Medium
keyword Exact match, filters IDs, statuses, tags, categories Low (not analyzed) High
integer/long Numeric values Prices, quantities, ages Low High
date Date/time Creation dates, update timestamps Low High
boolean Flags is_active, is_deleted Very low High
object Nested object Structured data of a single object Medium Medium
nested Array of objects Products with variants requiring accurate inner search High (extra structure) Low
geo_point Geo-coordinates Map points, geo search Low High
dense_vector Vector representation Semantic search, recommendations High (dimensionality) Low

How to Choose Field Type for Your Data

For full-text search, use text with a keyword sub-field for sorting. For exact matching — keyword. Numeric ranges — integer or long. Dates — date. If you have an array of objects and need correct filtering across related fields, choose nested. Otherwise object is sufficient. For geo data — geo_point. Vector search requires dense_vector. In 95% of projects, selecting the correct field type reduces index size by 20–30% immediately.

Creating an Index with Explicit Mapping: Step-by-Step

  1. Identify fields and their semantics, considering what data will be stored and which fields are needed for search, filtering, sorting.
  2. Choose types from the table above. Remember that text is analyzed, keyword is not.
  3. Configure analyzers for text fields. For Russian text, use snowball with a stop filter.
  4. Set dynamic: strict to protect against accidental schema changes.
  5. Create the index via PUT request with mapping. Example below.
PUT /products { "settings": { "number_of_shards": 3, "number_of_replicas": 1, "analysis": { "analyzer": { "product_search": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "stop", "snowball"] } } } }, "mappings": { "dynamic": "strict", "_source": { "enabled": true }, "properties": { "id": { "type": "keyword" }, "title": { "type": "text", "analyzer": "product_search", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "description": { "type": "text", "analyzer": "product_search", "index_options": "positions" }, "category": { "type": "keyword" }, "tags": { "type": "keyword" }, "price": { "type": "scaled_float", "scaling_factor": 100 }, "stock": { "type": "integer" }, "is_active": { "type": "boolean" }, "created_at": { "type": "date", "format": "strict_date_optional_time||epoch_millis" }, "attributes": { "type": "nested", "properties": { "name": { "type": "keyword" }, "value": { "type": "keyword" } } }, "location": { "type": "geo_point" } } } } 

"dynamic": "strict" rejects documents with unknown fields. Alternatives: "true" (auto-add), "false" (ignore unknown fields, not indexed). Maintaining a static mapping typically costs half as much as dynamic due to lower storage and faster search.

Index Templates for Automation

Index templates automatically apply mapping to new indices matching a pattern. Indispensable for data streams and rolling indices, like logs.

PUT _index_template/logs-template { "index_patterns": ["logs-*"], "priority": 100, "template": { "settings": { "number_of_shards": 1, "number_of_replicas": 1, "index.lifecycle.name": "logs-policy", "index.lifecycle.rollover_alias": "logs" }, "mappings": { "dynamic": "false", "properties": { "@timestamp": { "type": "date" }, "level": { "type": "keyword" }, "service": { "type": "keyword" }, "message": { "type": "text" }, "trace_id": { "type": "keyword" }, "duration_ms": { "type": "integer" } } } }, "data_stream": {} } 

How to Change Mapping on an Existing Index

Most mapping changes require reindexing. You can only add new fields or extend parameters (ignore_above, adding fields). You cannot change the type of an existing field. To add a field:

PUT /products/_mapping { "properties": { "brand": { "type": "keyword" } } } 

To change a type — create a new index, run _reindex, and switch the alias. For example, to reindex products_v1 to products_v2, run: POST _reindex { "source": { "index": "products_v1" }, "dest": { "index": "products_v2" } }. The full reindexing process is described in the Reindex API documentation.

Index Aliases

Aliases abstract the application from the physical index name. Switching aliases is atomic — no code changes. Example:

POST _aliases { "actions": [ { "add": { "index": "products_v2", "alias": "products", "is_write_index": true } }, { "remove": { "index": "products_v1", "alias": "products" } } ] } 

_source and Storage Optimization

_source stores the original JSON document. Disabling it saves space but loses the ability to use update, reindex, and highlight without the original. In most cases you don't need to disable it. To save space, you can exclude heavy fields from _source via _source.excludes.

What Our Index Tuning Service Includes

  • Audit of current schema and queries — identify bottlenecks like N+1 queries or suboptimal field types.
  • Mapping design aligned with business logic — choose types, analyzers, set dynamic: strict.
  • Analyzer configuration for language and tasks — for Russian we use snowball with stop filter, for English — english.
  • Index templates and ILM policies — automate index management, saving up to 40% on storage.
  • Zero-downtime reindexing via aliases — the application keeps running while data is copied.
  • Documentation and team training — transfer knowledge so you can maintain the schema yourself.

Deliverables include: mapping JSON, comprehensive documentation, access to reindexing scripts, 2 hours of training session, and 30 days of post-deployment support.

Typical Timeframes

Designing a mapping for a new index takes 4 to 8 hours. If it includes reindexing existing data and alias switching, add 2–4 hours. For complex schemas with nested objects and custom analyzers — up to 2 business days. The price is calculated individually, typically ranging from 30,000 to 80,000 rubles depending on index complexity.

Common Mistakes to Avoid

  • Using dynamic mapping in production — always switch to strict or at least false.
  • Choosing text where keyword is sufficient — this bloats the index and slows aggregations.
  • Storing large fields in _source unnecessarily — use _source.excludes or disable _source for fields that are only used in searches.
  • Forgetting to define analyzers for non-English text — the default analyzer treats every word separately, missing stemming.
  • Not using aliases for zero-downtime reindexing — leads to application downtime during schema changes.

Order mapping design — get a consultation from an engineer. We will analyze your schema and propose optimizations that can speed up search 2–3 times and reduce storage costs by up to 40%.