# Elasticsearch Types: From Multiple Mappings to Removal in Version 8.0

> Understand Elasticsearch types, their role from version 5, and why they were removed in 8.0. Learn about the shift to a single _doc type for modern search.

- Repository: [elastic/elasticsearch](https://github.com/elastic/elasticsearch)
- Tags: deep-dive
- Published: 2026-02-16

---

**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`](https://github.com/elastic/elasticsearch/blob/main/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`](https://github.com/elastic/elasticsearch/blob/main/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`](https://github.com/elastic/elasticsearch/blob/main/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`](https://github.com/elastic/elasticsearch/blob/main/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`](https://github.com/elastic/elasticsearch/blob/main/server/src/test/java/org/elasticsearch/search/fetch/subphase/FetchFieldsPhaseTests.java).

### Mapping API Changes

In [`server/src/main/java/org/elasticsearch/metadata/MappingMetaData.java`](https://github.com/elastic/elasticsearch/blob/main/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`](https://github.com/elastic/elasticsearch/blob/main/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:

```json
{
  "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 `_id` or custom routing values, rather than the complex combination of `_id` plus `_type`.
- **Performance Optimization**: The `_type` field required additional bookkeeping in the Lucene layer; removing it reduces memory overhead and CPU cycles in [`MapperService.java`](https://github.com/elastic/elasticsearch/blob/main/MapperService.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
// 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

```json
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

```json
GET my-index/_search
{
  "query": {
    "match": { "title": "types" }
  }
}

```

Referencing `_type` in queries is ignored and generates a deprecation warning as verified in [`FetchFieldsPhaseTests.java`](https://github.com/elastic/elasticsearch/blob/main/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 `_type` field from index metadata and [`MapperService.java`](https://github.com/elastic/elasticsearch/blob/main/MapperService.java) logic.
- Modern APIs require mapping JSON to start directly with `"properties"`, and the `_doc` endpoint 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`](https://github.com/elastic/elasticsearch/blob/main/server/src/main/java/org/elasticsearch/index/mapper/MapperService.java), the field is no longer created or stored, and the test [`FetchFieldsPhaseTests.java`](https://github.com/elastic/elasticsearch/blob/main/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`.