Today submitting an unbatched `ClusterStateUpdateTask` to the `MasterService` is deprecated, and devs are encouraged to write their own batching executor instead. In principle this makes it possible to combine updates without incurring the costs of building a whole new `ClusterState` on each iteration, but in practice most implementations don't work at a lower level and just iteratively update a `ClusterState`. Moreover creating new `ClusterState` instances is nothing like as expensive as once it was.

We should accept this and provide some friendlier utilities for writing batched cluster state updates, ideally leaving the developer to express the desired per-task update as a `ClusterState -> ClusterState` operator.
server/src/main/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateService.java
+ "would cause tsdb data streams "
                    + dataStreamsWithNonTsdbTemplate
                    + " to no longer match a data stream template with a time_series index_mode"
            );
        }
    }
    /**
     * Return a map of v1 template names to their index patterns for v1 templates that would overlap
     * with the given v2 template's index patterns.
     */
    public static Map<String, List<String>> findConflictingV1Templates(
        final ClusterState state,
        final String candidateName,
        final List<String> indexPatterns
    ) {
        Automaton v2automaton = Regex.simpleMatchToAutomaton(indexPatterns.toArray(Strings.EMPTY_ARRAY));
        Map<String, List<String>> overlappingTemplates = new HashMap<>();
        for (Map.Entry<String, IndexTemplateMetadata> cursor : state.metadata().templates().entrySet()) {
            String name = cursor.getKey();
            IndexTemplateMetadata template = cursor.getValue();
            Automaton v1automaton = Regex.simpleMatchToAutomaton(template.patterns().toArray(Strings.EMPTY_ARRAY));
            if (Operations.isEmpty(Operations.intersection(v2automaton, v1automaton)) == false) {
                logger.debug(
                    "composable template {} and legacy template {} would overlap: {} <=> {}",
                    candidateName,
                    name,
                    indexPatterns,
                    template.patterns()
                );
                overlappingTemplates.put(name, template.patterns());