Last-Modified — essência, mecanismo e configuração do cabeçalho de data de modificação

Autor: IT Sectr Publicado: 2026-03-09 Tempo de leitura: 9 min

Last-Modified é um cabeçalho de resposta HTTP que indica a data e hora da última modificação de um recurso no servidor, permitindo que o cliente faça requisições condicionais via If-Modified-Since. Se o recurso não mudou desde a data especificada, o servidor retorna 304 Not Modified sem enviar o corpo da resposta, economizando significativamente largura de banda. De acordo com RFC 7232 (IETF, 2014), requisições condicionais com Last-Modified reduzem o tempo de carregamento de páginas em 30-60% em visitas repetidas. O cabeçalho é automaticamente suportado pela maioria dos servidores HTTP e proxies.

Principais Pontos

  • Last-Modified — cabeçalho HTTP com a data da última modificação do recurso para requisições condicionais If-Modified-Since
  • 304 Not Modified — resposta do servidor se o recurso não mudou; o cliente usa sua cópia em cache
  • Precisão de segundo — limitação do cabeçalho: alterações dentro de um segundo podem passar despercebidas
  • Trabalha junto com ETag — o servidor retorna ambos os cabeçalhos, o cliente envia ambas as requisições condicionais
  • Geração automática — Nginx e Apache definem Last-Modified para estáticos a partir do sistema de arquivos

O que é Last-Modified?

Last-Modified é um cabeçalho HTTP que pertence ao grupo de cabeçalhos de requisições condicionais. O servidor o adiciona a uma resposta GET ou HEAD, indicando a data e hora da última modificação do recurso solicitado no formato HTTP-date: Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT. O cliente (navegador, aplicativo móvel, proxy) armazena esta data junto com o recurso em cache. Em uma requisição repetida, o cliente envia o cabeçalho If-Modified-Since com a mesma data, e o servidor a compara com o momento atual de modificação do recurso.

O protocolo de requisições condicionais com Last-Modified é definido na RFC 7232 e suportado por todos os servidores HTTP modernos. O formato da data é estritamente regulamentado — apenas GMT (Greenwich Mean Time) sem indicação de fuso horário. O servidor deve retornar a data em três formatos possíveis: RFC 1123 (padrão), RFC 850 (obsoleto) ou ANSI C asctime. Na prática, quase todos os servidores usam o formato RFC 1123 com comprimento fixo de 29 caracteres.

Last-Modified pertence à categoria de mecanismos de validação de cache: ele não diz ao cliente se a resposta pode ser armazenada em cache, mas fornece uma ferramenta para verificar a atualidade de um recurso já em cache. A política de cache é definida separadamente pelo cabeçalho Cache-Control. De acordo com um estudo da Akamai (2025), a configuração adequada de Last-Modified junto com Cache-Control reduz a carga nos servidores de origem em até 70% para conteúdo estático.

Quando o Last-Modified apareceu

O cabeçalho Last-Modified foi definido ainda no HTTP/1.0 (RFC 1945, 1996) e se tornou um dos primeiros mecanismos de gerenciamento de cache na web. Antes do surgimento do ETag no HTTP/1.1, era a única maneira de fazer requisições condicionais. Apesar da idade, o cabeçalho permanece relevante devido à sua simplicidade — o servidor não precisa calcular um hash do conteúdo, basta ler o timestamp do arquivo do sistema de arquivos ou o campo updated_at do banco de dados.

Como funciona o Last-Modified?

O ciclo completo consiste em três etapas. Na primeira requisição, o servidor retorna o recurso com o cabeçalho Last-Modified e status HTTP 200 OK. O cliente armazena em cache a resposta junto com a data. Em uma requisição repetida, o cliente envia o cabeçalho If-Modified-Since com a data salva. O servidor compara esta data com o momento atual de modificação do recurso. Se o recurso não mudou — retorna 304 Not Modified com corpo vazio. Se mudou — 200 OK com novos dados e um novo Last-Modified.

http
// Primeira requisição — servidor retorna o recurso com uma data
HTTP/1.1 200 OK
Content-Type: application/json
Last-Modified: Wed, 02 Jul 2025 14:30:00 GMT

[{"id": 1, "name": "Alice"}]

// Requisição repetida — cliente envia a data salva
GET /api/users HTTP/1.1
Host: example.com
If-Modified-Since: Wed, 02 Jul 2025 14:30:00 GMT

// Resposta — dados não mudaram
HTTP/1.1 304 Not Modified

Para aplicativos móveis, o Last-Modified é especialmente útil para sincronização de dados. O aplicativo armazena a data da última atualização bem-sucedida e a envia ao servidor no If-Modified-Since. Se houver mais dados ou eles tiverem mudado — o servidor retorna o conjunto completo. Se não — 304, e o aplicativo usa a cópia local. OkHttp e URLSession suportam este mecanismo automaticamente através de sistemas de cache integrados.

Como o servidor determina a data

Para arquivos estáticos, Nginx e Apache obtêm a data dos atributos do sistema de arquivos — mtime (hora de modificação). Para conteúdo dinâmico, o código do servidor deve definir explicitamente o Last-Modified com base na lógica de negócios: o campo updated_at do banco de dados, a data do último commit no Git, o timestamp do artefato de build. Se Last-Modified não for definido explicitamente, o servidor pode não enviar o cabeçalho, e o cliente não poderá fazer requisições condicionais por data.

Last-Modified vs ETag

Last-Modified e ETag realizam uma tarefa similar — permitir que o cliente verifique a atualidade do cache — mas têm diferenças fundamentais. Last-Modified usa um timestamp, ETag usa um identificador único de versão. Cada abordagem tem seus cenários onde é mais eficaz, e a especificação HTTP recomenda usar ambos os cabeçalhos juntos.

CritérioLast-ModifiedETag
EssênciaData da última modificaçãoIdentificador único de versão
PrecisãoAté um segundoAté um bit (hash)
Complexidade de implementaçãoBaixa — automática do sistema de arquivosMédia — requer cálculo de hash
Servidores em clusterProblema: mtime pode diferir entre nósEstável com dados idênticos entre nós
Suporte a intervalosNão afeta requisições RangeRequer ETag forte para intervalos
RecomendaçãoPara estáticos e APIs simplesPara APIs onde precisão é importante

A principal vantagem do Last-Modified é a simplicidade. O servidor não precisa calcular um hash do conteúdo, economizando recursos de CPU em cada requisição. Para projetos de alto tráfego servindo arquivos estáticos ou dados com timestamps claros, Last-Modified continua sendo a escolha ótima. ETag, por outro lado, fornece precisão absoluta — alterar uma única letra em uma resposta JSON mudará o ETag, mas pode não mudar a data (se o arquivo foi sobrescrito com a mesma versão).

Uso conjunto

A especificação recomenda retornar ambos os cabeçalhos simultaneamente. O servidor inclui tanto Last-Modified quanto ETag na resposta 200 OK. O cliente envia ambos os cabeçalhos condicionais — If-Modified-Since e If-None-Match. O servidor verifica primeiro o ETag (tem prioridade), depois o Last-Modified. Se pelo menos um sinalizar uma mudança — a resposta completa é retornada. Isso oferece máxima flexibilidade: ETag garante precisão, Last-Modified fornece uma verificação de fallback para clientes que não suportam ETag.

Configuração do Last-Modified no servidor

A configuração do Last-Modified depende do tipo de servidor. Para Nginx e Apache, Last-Modified é definido automaticamente para arquivos estáticos com base no mtime. Para aplicações dinâmicas, o cabeçalho deve ser definido no código do servidor. Vamos ver a configuração em plataformas populares.

javascript
// Express.js — definindo Last-Modified
app.get("/api/users", async (req, res) => {
    const updatedAt = await getLastUpdate()
    const ifModifiedSince = req.get("If-Modified-Since")

    // Verificando If-Modified-Since
    if (ifModifiedSince && new Date(ifModifiedSince)
        >= updatedAt) {
        return res.status(304).end()
    }

    const users = await getUsers()
    res.set("Last-Modified", updatedAt.toUTCString())
    res.json(users)
})

No exemplo Express.js, o servidor obtém a data da última atualização dos dados do banco, verifica If-Modified-Since do cliente e, se o cache ainda estiver atual, retorna 304. Se os dados mudaram — define um novo Last-Modified e retorna a resposta completa. toUTCString() converte a data para o formato HTTP exigido. Em produção, é bom armazenar updatedAt em cache no Redis para evitar consultar o banco a cada requisição.

Nginx: configurando Last-Modified

Nginx define automaticamente Last-Modified para arquivos estáticos com base na hora da última modificação do arquivo. É possível desabilitar ou alterar este comportamento usando a diretiva etag (desabilitando ETag) ou através do módulo ngx_http_headers_module. Para requisições proxy ao backend, Last-Modified é passado da resposta upstream sem alterações. Importante: se o backend não retornar Last-Modified, o Nginx não o adicionará automaticamente para respostas dinâmicas.

Limitações e armadilhas

Last-Modified tem várias limitações conhecidas. A principal é a precisão de segundo. Se um recurso mudar duas vezes dentro de um segundo, o cliente pode perder a nova versão. Na prática isso é um cenário raro, mas para atualizações de alta frequência (feeds de cotações, chats) o ETag é recomendado. A segunda limitação é o problema de clusterização: em servidores diferentes, um arquivo pode ter mtime diferente devido a cópia ou deploy, tornando o Last-Modified inconsistente.

A terceira limitação — o manuseio de If-Modified-Since com precisão de segundo pode levar a requisições desnecessárias ao consultar o servidor com frequência. Se o cliente envia If-Modified-Since a cada 500 ms, o servidor retorna 200 OK toda vez porque a data não mudou, mas o recurso já foi atualizado. A solução é usar uma combinação com ETag: ETag detectará a mudança dentro de um segundo, enquanto Last-Modified permanece como fallback.

O quarto problema — Last-Modified não distingue entre diferentes versões do mesmo recurso com a mesma data. Se um arquivo for restaurado de um backup e seu mtime coincidir com o original, o cliente não notará que o conteúdo mudou. ETag resolve este problema: o hash do conteúdo mudará garantidamente com qualquer alteração nos dados, independentemente do timestamp. Para dados críticos, sempre use ambos os cabeçalhos.

  • Precisão de segundo — não detecta mudanças dentro de um segundo; use ETag para atualizações de alta frequência
  • Clusterização — mtime pode diferir entre servidores; sincronize via NTP ou use ETag
  • Condição de corrida — se o recurso mudar depois de enviar If-Modified-Since mas antes da verificação do servidor
  • Má interpretação por proxy — alguns proxies podem alterar Last-Modified ao cachear; HTTPS resolve

Perguntas Frequentes

Qual formato de data é usado no Last-Modified?

Apenas GMT (Greenwich Mean Time) no formato RFC 1123: dia da semana, dia, mês, ano, horas:minutos:segundos. Exemplo: Wed, 02 Jul 2025 14:30:00 GMT. O fuso horário é sempre GMT, outros formatos não são permitidos.

Last-Modified pode estar no futuro?

Tecnicamente sim, mas viola a RFC 7232. Se o servidor retornar uma data futura, os clientes não atualizarão o recurso até que essa data chegue. Tal configuração é considerada um erro — a data deve estar no passado ou presente.

Last-Modified funciona com requisições POST?

Não, requisições condicionais If-Modified-Since funcionam apenas com GET e HEAD. Requisições POST não são armazenadas em cache e não usam validação por data. Para verificações de atualidade em POST, use ETag ou mecanismos personalizados.

Como Last-Modified interage com Cache-Control?

Cache-Control define a política de cache (tempo máximo de armazenamento, quem pode cachear), enquanto Last-Modified é um mecanismo de validação para cache expirado. Após o término do max-age, o cliente envia If-Modified-Since para verificar a atualidade.

O que fazer se Last-Modified não mudar ao atualizar dados?

Verifique se o servidor está realmente definindo o cabeçalho a partir da fonte correta — banco de dados, sistema de arquivos ou API. Para respostas dinâmicas, certifique-se de chamar explicitamente res.setHeader(“Last-Modified”, ...) no código do manipulador.

Resumo

  • Last-Modified — cabeçalho HTTP com a data da última modificação do recurso para requisições condicionais 304
  • Implementação simples — funciona automaticamente para estáticos (mtime) e requer mínimo código para APIs
  • Precisão de segundo — a principal limitação; para mudanças de alta frequência use ETag
  • ETag é mais preciso, Last-Modified é mais simples — combinação ótima: ambos os cabeçalhos juntos
  • Formato de data HTTP — apenas GMT, RFC 1123, comprimento fixo de 29 caracteres
  • Clusterização — requer sincronização de horário (NTP) ou usar ETag como mecanismo principal
  • Recomendação — sempre adicione Last-Modified para APIs e ative para estáticos via Nginx/Apache

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também