Eles são um pouco diferentes - o ETag não possui nenhuma informação que o cliente possa usar para determinar se deve ou não fazer uma solicitação para esse arquivo novamente no futuro. Se ETag é tudo o que tem, sempre será necessário fazer uma solicitação. No entanto, quando o servidor lê o ETag na solicitação do cliente, ele pode determinar se deve enviar o arquivo (HTTP 200) ou dizer ao cliente para usar apenas sua cópia local (HTTP 304). Um ETag é basicamente apenas uma soma de verificação para um arquivo que muda semanticamente quando o conteúdo do arquivo é alterado.
O cabeçalho Expira é usado pelo cliente (e proxies / caches) para determinar se ele precisa ou não fazer uma solicitação ao servidor. Quanto mais próximo você estiver da data de validade, maior a probabilidade de o cliente (ou proxy) fazer uma solicitação HTTP para esse arquivo do servidor.
Então, na verdade, o que você quer fazer é usar AMBOS cabeçalhos - defina o cabeçalho Expira para um valor razoável com base na frequência com que o conteúdo muda. Em seguida, configure ETags para serem enviados para que, quando os clientes enviarem uma solicitação ao servidor, ele possa determinar com mais facilidade se deve ou não enviar o arquivo de volta.
Uma última observação sobre o ETag - se você estiver usando uma configuração de servidor com balanceamento de carga com várias máquinas executando o Apache, provavelmente desejará desativar a geração do ETag. Isso ocorre porque os inodes são usados como parte do algoritmo de hash ETag, que será diferente entre os servidores. Você pode configurar o Apache para não usar inodes como parte do cálculo, mas deseje garantir que os carimbos de data e hora nos arquivos sejam exatamente iguais, para garantir que o mesmo ETag seja gerado para todos os servidores.