An index template before the first document

Field types are decided by whichever document arrives first, so a field that is an integer in one service and a string in another is rejected in the second — silently.

PUT /_template/logs
{
  "index_patterns": ["logs-*"],
  "settings": { "number_of_shards": 1, "number_of_replicas": 1 },
  "mappings": {
    "dynamic_templates": [
      { "strings": { "match_mapping_type": "string",
                     "mapping": { "type": "keyword", "ignore_above": 1024 }}}
    ],
    "properties": { "@timestamp": { "type": "date" } }
  }
}

Defaulting strings to keyword rather than analysed text is the decision worth making up front: analysed text is for prose, and a hostname or a status code is a value to filter and aggregate on. Getting it wrong doubles the index size and makes exact matching unreliable. Changing a mapping after documents exist means a reindex, which is why the template has to precede the first write.