An ETag costs nothing to emit and saves the response body only if clients actually send the conditional header back.
GET /api/orders/8814
→ 200 OK
ETag: "a41f2b8"
GET /api/orders/8814
If-None-Match: "a41f2b8"
→ 304 Not Modified # no body
# and the other direction, which is the underused one:
PUT /api/orders/8814
If-Match: "a41f2b8"
→ 412 Precondition Failed # somebody else changed it
The write side is where ETag earns its place: If-Match gives optimistic concurrency control for free, so two clients editing the same resource produce a 412 instead of a silent overwrite. The read side depends on clients being well behaved and mostly they are not, so the saving is smaller than expected. Generating the tag from a version column rather than hashing the body is cheaper and avoids rendering the response to find out it was not needed.