In my decoupled Drupal + Next.js setup, editing or deleting a redirect entity has no effect on the Next.js frontend cache. The stale redirect continues to be served to visitors even after the change is saved in Drupal.
Steps to reproduce:
- Have a Next.js frontend with
"use cache"(or ISR) enabled. - Visit a URL that resolves via a Drupal redirect, e.g.
/old-blogredirects to/blog/my-post. The frontend caches this resolution. - In Drupal, edit that redirect (change the source, destination, or status code) or delete it entirely.
- Visit
/old-blogon the frontend again — it still serves the old cached redirect. Drupal's revalidation signal had no effect.
Expected: The Next.js cache for the affected path is cleared after the redirect is changed or deleted, so the next visit reflects the current Drupal state.
Actual: The cache is never cleared. The Path revalidator sends ?path=/admin/config/search/redirect/edit/42 (the redirect entity's canonical URL in Drupal, which is its admin form) to Next.js instead of the frontend source path like ?path=/old-blog. Next.js has no cached entry for the admin URL, so the revalidation is a silent no-op.
Proposed resolutions:
Option 1: Patch the existing Path plugin
Add a redirect-aware branch inside Path::revalidate(). When the entity being saved is a Redirect, use $entity->getSource()['path'] instead of $event->getEntityUrl() to build the revalidation path. This keeps everything in one place but introduces a redirect module dependency into the next module's core Path plugin.
Additionally, to handle source renames (where both the old and new paths need revalidating), EntityActionEvent::createFromEntity() would need to capture $entity->original onto the event object at construction time, because by the time the revalidator runs at kernel.terminate, core has already called unset($entity->original). A new getOriginalEntity() getter on the event would expose this to any revalidator.
Option 2: Create a new dedicated Redirect revalidator plugin
Add a separate plugin (e.g. redirect_path) that handles redirect entities exclusively. It reads $entity->getSource()['path'] for the current source and uses the same getOriginalEntity() approach for the old source on rename. This keeps the existing Path plugin clean and dependency-free, and gives site builders a dedicated option to select for redirect entity types.
Please help me on deciding which approach is better.
Comments
Comment #2
jatin.buzz commented