I made a change to an endpoint that updated a product's price and called revalidatePath('/productos'). It worked. The price updated. What I didn't see until two days later is that same route was also serving filters, categories, and a comparison view that depended on the same layout — and all of that got regenerated from scratch on the next request, even though none of it had changed. Cache thrown in the trash from over-invalidating.
That's when I understood it wasn't a "which function do I use" problem — I was thinking in routes when I needed to be thinking in data. revalidatePath invalidates by where content lives. revalidateTag invalidates by what the content is. These are two different granularities, and picking the wrong one doesn't break anything visually — it breaks your cache silently, in a way you only notice by staring at build metrics or response times.
My take is simple: revalidatePath is the brute-force tool and revalidateTag is the precision one, and most people default to the first because it's the one that shows up first in the docs examples, not because it's the right call for their case. That's the actual thesis here, not just "these are two functions, use the right one" — the real cost is invisible until you go looking for it in your infra bill or your response times.






