Вони дещо відрізняються - ETag не має жодної інформації, яку клієнт може використати, щоб визначити, чи потрібно подавати запит на цей файл у майбутньому. Якщо ETag - це все, що він має, він завжди повинен буде зробити запит. Однак, коли сервер читає ETag з клієнтського запиту, сервер може визначити, чи надсилати файл (HTTP 200) або сказати клієнту просто використовувати їх локальну копію (HTTP 304). ETag - це лише контрольна сума для файлу, який семантично змінюється, коли зміст файлу змінюється.
Заголовок Expires використовується клієнтом (та проксі-серверами / кешами) для визначення, чи потрібно взагалі робити запит на сервер чи ні. Чим ближче ви до дати закінчення, тим більше шансів, що клієнт (або проксі) зробить HTTP-запит на цей файл із сервера.
Тому дійсно те, що ви хочете зробити, це використовувати заголовки BOTH - встановіть заголовок Expires на прийнятне значення, залежно від того, як часто змінюється вміст. Потім налаштуйте ETags для надсилання так, що коли клієнти DO надсилають запит на сервер, він може легше визначити, повертати файл чи ні.
Останнє зауваження про ETag - якщо ви використовуєте налаштування сервера з урівноваженим завантаженням на декількох машинах під керуванням Apache, ви, ймовірно, захочете вимкнути генерацію ETag. Це відбувається тому, що inode використовуються як частина алгоритму хешування ETag, який буде відрізнятися між серверами. Ви можете налаштувати Apache не використовувати inode як частину обчислення, але тоді ви хочете переконатися, що часові позначки на файлах точно однакові, щоб забезпечити генерування одного і того ж ETag для всіх серверів.