Use a canonical when both URLs still need to exist for users, and a 301 redirect when one of them should stop existing. That single question, whether the old URL still needs to load for anyone, is the whole decision; the two aren’t interchangeable ways to merge pages, they do different things to the URL you are consolidating away.

A canonical keeps both pages live. It marks one URL as the version to index and lets the ranking signals settle there, while the other URL stays reachable and a visitor who lands on it sees the page normally. That is what you want when the duplicate has a reason to exist, a product reachable through several category paths, a URL carrying tracking parameters, a filtered or sorted view, content syndicated elsewhere, where killing the URL would break something for users even though only one version should rank.

A 301 does the opposite: it removes the old URL. Visitors who request it are sent straight to the destination, the old page no longer loads, and Google moves the traffic and nearly all the ranking signal to the new URL and drops the old one from the index over time. That is the tool for a permanent change, a renamed slug, a site or domain move, two pages merged into one, an outdated page folded into a current one, where the old address has no further job.

So before reaching for either, ask whether the old URL still needs to load for anyone. If it does, use a canonical and keep both live; if it doesn’t, use a 301 and let the old one go, rather than treating the two as the same move.