Elasticsearch Types: From Multiple Mappings to Removal in Version 8.0
Elasticsearch types were logical document groupings within an index that were completely removed in version 8.0, leaving only a single implicit _doc type for backward compatibility.
In the elastic/elasticsearch codebase, elasticsearch types historically allowed a single index to store multiple document schemas. Understanding this evolution—from full support in version 5.x through deprecation in 6.x/7.x to complete removal in 8.0—is critical for modern cluster architecture and migration planning.
What Are Elasticsearch Types?
In early Elasticsearch versions, a type represented a logical category of documents within an index that shared the same field mappings. Each document stored a hidden _type field identifying its type, allowing queries to filter by type or aggregate across types within the same index.
For example, a single ecommerce index might contain product and review types, each with distinct schemas but coexisting in the same Lucene index.
The Evolution of Types in Elasticsearch 5.x Through 8.0
Version 5.x: Multiple Types Supported
Elasticsearch 5.x fully supported multiple types per index. Users defined mappings under type names in the mapping JSON, and the _type field was actively used for routing and storage in MapperService.java.
Version 6.x and 7.x: Deprecation and Single-Type Restriction
Starting with 6.x, Elasticsearch restricted indices to a single type and began emitting deprecation warnings. Version 7.x continued this transition, routing all documents through a default _doc type while maintaining the _type field for backward compatibility.
Version 8.0 and Above: Complete Removal
In the S series (Elasticsearch 8.0 and onwards), the type concept was completely removed. According to the breaking changes documented in docs/release-notes/breaking-changes.md at lines 304-306, index-level APIs no longer accept type names, and the _type field is neither created nor stored in index metadata.
Technical Implementation of Type Removal
The _type Field Deprecation
In server/src/main/java/org/elasticsearch/index/mapper/MapperService.java, the code that previously managed multiple mapping types was stripped. The _type field can still be referenced in query DSL for backward compatibility, but it is ignored and triggers a deprecation warning.
The unit test FetchFieldsPhaseTests.java at lines 226-228 explicitly verifies that _type is no longer a required stored field, confirming the removal in server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchFieldsPhaseTests.java.
Mapping API Changes
In server/src/main/java/org/elasticsearch/metadata/MappingMetaData.java, the metadata container now holds a single implicit type name (_doc) for legacy compatibility, while DocumentMapper.java instantiates exactly one mapper per index.
Modern mapping definitions no longer wrap properties in a type name. The mapping JSON starts directly with the "properties" object:
{
"properties": {
"title": { "type": "text" },
"timestamp": { "type": "date" }
}
}
Why Elasticsearch Removed Types
The removal of elasticsearch types addresses several architectural limitations:
- Simpler Data Model: Eliminating types removes the need to manage hidden fields and prevents cross-type field name collisions within the same index.
- Consistent Routing: Documents route solely by
_idor custom routing values, rather than the complex combination of_idplus_type. - Performance Optimization: The
_typefield required additional bookkeeping in the Lucene layer; removing it reduces memory overhead and CPU cycles inMapperService.java. - Lucene Alignment: Lucene segments never truly supported multiple types; the change aligns Elasticsearch with its underlying storage engine.
Practical Code Examples
Creating an Index Without Types (Java High-Level REST Client)
// Java client - index creation without type specification
CreateIndexRequest request = new CreateIndexRequest("my-index");
request.mapping(
"{ \"properties\": { " +
" \"title\": { \"type\": \"text\" }, " +
" \"timestamp\": { \"type\": \"date\" } " +
"} }",
XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);
Note that the mapping JSON starts directly with properties, with no type name wrapper.
Indexing Documents
POST my-index/_doc/1
{
"title": "Elasticsearch types removed",
"timestamp": "2026-02-16T12:00:00Z"
}
The endpoint uses _doc as a placeholder, but this refers to the index itself, not a distinct type.
Querying Without Type Filters
GET my-index/_search
{
"query": {
"match": { "title": "types" }
}
}
Referencing _type in queries is ignored and generates a deprecation warning as verified in FetchFieldsPhaseTests.java.
Summary
- Elasticsearch types were logical document groupings within an index that allowed multiple schemas to coexist prior to version 8.0.
- Version 5.x supported multiple types per index with distinct mappings, while versions 6.x and 7.x restricted indices to single types and began deprecation.
- Elasticsearch 8.0+ completely removed types, eliminating the
_typefield from index metadata andMapperService.javalogic. - Modern APIs require mapping JSON to start directly with
"properties", and the_docendpoint serves as a legacy-compatible placeholder. - The removal improves performance, simplifies the data model, and aligns Elasticsearch with underlying Lucene architecture.
Frequently Asked Questions
What happened to the _type field in Elasticsearch 8.0?
The _type field was completely removed from index metadata in Elasticsearch 8.0. According to the source code in server/src/main/java/org/elasticsearch/index/mapper/MapperService.java, the field is no longer created or stored, and the test FetchFieldsPhaseTests.java at lines 226-228 confirms it is no longer a required stored field. While queries can still reference _type for backward compatibility, the value is ignored and triggers a deprecation warning.
Can I use multiple types in Elasticsearch 5.x?
Yes, Elasticsearch 5.x fully supports multiple types per index. You can define distinct mappings for different document categories within the same index, and each document stores a hidden _type field identifying its logical group. However, this functionality was restricted starting in version 6.0 and completely removed in version 8.0.
How do I create mappings without types in modern Elasticsearch?
In Elasticsearch 8.0 and later, mappings are defined without type wrappers. The mapping JSON must start directly with the "properties" object containing your field definitions. When using the Java High-Level REST Client, pass this JSON to CreateIndexRequest.mapping(). The REST API endpoint uses _doc as a placeholder (e.g., PUT my-index/_doc/1), but this refers to the index itself rather than a distinct type schema.
Why did Elasticsearch remove the type system?
Elasticsearch removed types to simplify the data model, improve routing consistency, and boost performance. The _type field required additional bookkeeping in the Lucene layer that consumed memory and CPU resources. Removing types aligns Elasticsearch with Lucene's underlying design, which never truly supported multiple types per segment. This change also eliminates cross-type field name collisions and makes document routing dependent solely on _id rather than a combination of _id and _type.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →