I was looking at a flame graph of an ingestion workload with @dliappis, and it looks like we parse the JSON representation of the index request twice when a document has both a pipeline and a final pipeline.

It's hard to know how much we would save on this benchmark since not all data streams in this benchmark had both a pipeline and a final pipeline, but the cost of parsing index request into maps of maps via IngestService represented 4.06% of overall CPU time according to the flame graph, so this might not be negligible.
server/src/test/java/org/elasticsearch/ingest/IngestServiceTests.java
assertThat(indexRequest2.getRawTimestamp(), nullValue());
        assertThat(indexRequest3.getRawTimestamp(), equalTo(100));
        assertThat(indexRequest4.getRawTimestamp(), equalTo(100));
        assertThat(indexRequest5.getRawTimestamp(), nullValue());
        assertThat(indexRequest6.getRawTimestamp(), equalTo(10));
        assertThat(indexRequest7.getRawTimestamp(), equalTo(100));
        
        
    }
    public void testResolveRequiredOrDefaultPipelineDefaultPipeline() {
        IndexMetadata.Builder builder = IndexMetadata.builder("idx")
            .settings(settings(Version.CURRENT).put(IndexSettings.DEFAULT_PIPELINE.getKey(), "default-pipeline"))
            .numberOfShards(1)
            .numberOfReplicas(0)
            .putAlias(AliasMetadata.builder("alias").writeIndex(true).build());
        Metadata metadata = Metadata.builder().put(builder).build();
        
        IndexRequest indexRequest = new IndexRequest("idx");
        boolean result = IngestService.resolvePipelines(indexRequest, indexRequest, metadata);
        assertThat(result, is(true));
        assertThat(indexRequest.isPipelineResolved(), is(true));
        assertThat(indexRequest.getPipeline(), equalTo("default-pipeline"));
        
        indexRequest = new IndexRequest("alias");
        result = IngestService.resolvePipelines(indexRequest, indexRequest, metadata);
        assertThat(result, is(true));
        assertThat(indexRequest.isPipelineResolved(), is(true));
        assertThat(indexRequest.getPipeline(), equalTo("default-pipeline"));
        
        IndexTemplateMetadata.Builder templateBuilder = IndexTemplateMetadata.builder("name1")