Мы переделали кастомный cache для nextjs Ранее мы рассказывали, как сделали собственный
cacheHandler для Next.js и начали сохранять не только кеш, но и информацию о ревалидации тегов.
Для этого рядом с кешем хранился отдельный манифест: у каждого тега была отметка времени последней ревалидации. Благодаря этому теги переживали перезапуск приложения, а новый процесс понимал, какие записи уже устарели. Но со временем решение стало сложнее самой проблемы.
Нам приходилось синхронизировать кешированные данные, теги и манифест ревалидации. Любое обновление должно было корректно изменить их состояние, а незавершённая запись или рассинхронизация файлов могли оставить кеш в неконсистентном состоянии. Особенно неприятно это становилось во время сборки и деплоя.
В итоге мы отказались от общего файлового манифеста и изменили принцип формирования ключей кеша.
Next.js позволяет привязывать
tags к кешированной записи и инвалидировать её через
revalidateTag, но сами теги не являются частью исходного cache key.
Мы начали использовать их ещё и как дополнительные идентификаторы файлов. Например, одним из таких тегов может быть commit id. Дополнительно передаём его в запросе через header, чтобы он участвовал в формировании уникального cache key.
Упрощённо получилось так:
<теги>:<исходный-cache-key>Например:
<commit-id>:<исходный-cache-key>То есть commit — не отдельный механизм кеширования, а один из параметров, связывающий кеш с конкретным состоянием контента. Вместо него это может быть версия, revision, hash или любой другой идентификатор. Теперь каждая версия кеша уникальна, а старые записи можно легко найти и удалить по тегам, которые участвуют в имени файла.
При этом мы остались внутри стандартных механизмов Next.js:
force-cache, tags и cacheHandler — без дополнительного манифеста и собственной системы ревалидации поверх Next.js.
Цена у подхода есть: старые записи нужно периодически удалять, иначе хранилище будет расти. Но фоновая очистка оказалась намного проще и надёжнее, чем синхронизация изменяемого манифеста во время обработки запросов.
Возможно, вся эта история кажется оверхедом. Но задача появилась из конкретного требования: сохранять кеш между сборками и гарантированно учитывать ревалидацию по тегам после рестартов и деплоев.