diff --git a/lib/modules/datasource/npm/__snapshots__/index.spec.ts.snap b/lib/modules/datasource/npm/__snapshots__/index.spec.ts.snap
index 02cf5b7c7e009e282cc0db5be1bd56375da9554b..643d0d75ba63df39c1afb7c8a645473fb2ed05e8 100644
--- a/lib/modules/datasource/npm/__snapshots__/index.spec.ts.snap
+++ b/lib/modules/datasource/npm/__snapshots__/index.spec.ts.snap
@@ -221,6 +221,7 @@ Marking the latest version of an npm package as deprecated results in the entire
       "dependencies": undefined,
       "devDependencies": undefined,
       "gitRef": undefined,
+      "isDeprecated": true,
       "releaseTimestamp": "2018-05-06T05:21:53.000Z",
       "version": "0.0.1",
     },
diff --git a/lib/modules/datasource/npm/get.spec.ts b/lib/modules/datasource/npm/get.spec.ts
index b101911166ee7b0f14454365d636d49c1fb84831..b19d4359e9394683b4761c087acc2c1728c37e90 100644
--- a/lib/modules/datasource/npm/get.spec.ts
+++ b/lib/modules/datasource/npm/get.spec.ts
@@ -4,7 +4,7 @@ import { ExternalHostError } from '../../../types/errors/external-host-error';
 import * as _packageCache from '../../../util/cache/package';
 import * as hostRules from '../../../util/host-rules';
 import { Http } from '../../../util/http';
-import { getDependency } from './get';
+import { CACHE_REVISION, getDependency } from './get';
 import { resolveRegistryUrl, setNpmrc } from './npmrc';
 
 jest.mock('../../../util/cache/package');
@@ -473,16 +473,31 @@ describe('modules/datasource/npm/get', () => {
     `);
   });
 
-  it('returns cached legacy', async () => {
-    packageCache.get.mockResolvedValueOnce({ some: 'result' });
-    const dep = await getDependency(http, 'https://some.url', 'some-package');
-    expect(dep).toMatchObject({ some: 'result' });
+  it('discards cache with no revision', async () => {
+    setNpmrc('registry=https://test.org\n_authToken=XXX');
+
+    packageCache.get.mockResolvedValueOnce({
+      some: 'result',
+      cacheData: { softExpireAt: '2099' },
+    });
+
+    httpMock
+      .scope('https://test.org')
+      .get('/@neutrinojs%2Freact')
+      .reply(200, {
+        name: '@neutrinojs/react',
+        versions: { '1.0.0': {} },
+      });
+    const registryUrl = resolveRegistryUrl('@neutrinojs/react');
+    const dep = await getDependency(http, registryUrl, '@neutrinojs/react');
+
+    expect(dep?.releases).toHaveLength(1);
   });
 
   it('returns unexpired cache', async () => {
     packageCache.get.mockResolvedValueOnce({
       some: 'result',
-      cacheData: { softExpireAt: '2099' },
+      cacheData: { revision: CACHE_REVISION, softExpireAt: '2099' },
     });
     const dep = await getDependency(http, 'https://some.url', 'some-package');
     expect(dep).toMatchObject({ some: 'result' });
@@ -492,6 +507,7 @@ describe('modules/datasource/npm/get', () => {
     packageCache.get.mockResolvedValueOnce({
       some: 'result',
       cacheData: {
+        revision: CACHE_REVISION,
         softExpireAt: '2020',
         etag: 'some-etag',
       },
@@ -508,6 +524,7 @@ describe('modules/datasource/npm/get', () => {
     packageCache.get.mockResolvedValueOnce({
       some: 'result',
       cacheData: {
+        revision: CACHE_REVISION,
         softExpireAt: '2020',
         etag: 'some-etag',
       },
diff --git a/lib/modules/datasource/npm/get.ts b/lib/modules/datasource/npm/get.ts
index 6018d41efbac4b61c60e120c8ef2e8a4091938bb..33f5da96829bda8dba06208cd37d27c55f60c7fe 100644
--- a/lib/modules/datasource/npm/get.ts
+++ b/lib/modules/datasource/npm/get.ts
@@ -14,6 +14,8 @@ import { joinUrlParts } from '../../../util/url';
 import type { Release, ReleaseResult } from '../types';
 import type { CachedReleaseResult, NpmResponse } from './types';
 
+export const CACHE_REVISION = 1;
+
 const SHORT_REPO_REGEX = regEx(
   /^((?<platform>bitbucket|github|gitlab):)?(?<shortRepo>[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+)$/,
 );
@@ -82,8 +84,8 @@ export async function getDependency(
     cacheNamespace,
     packageUrl,
   );
-  if (cachedResult) {
-    if (cachedResult.cacheData) {
+  if (cachedResult?.cacheData) {
+    if (cachedResult.cacheData.revision === CACHE_REVISION) {
       const softExpireAt = DateTime.fromISO(
         cachedResult.cacheData.softExpireAt,
       );
@@ -94,8 +96,10 @@ export async function getDependency(
       }
       logger.trace('Cached result is soft expired');
     } else {
-      logger.trace('Reusing legacy cached result');
-      return cachedResult;
+      logger.trace(
+        `Package cache for npm package "${packageName}" is from an old revision - discarding`,
+      );
+      delete cachedResult.cacheData;
     }
   }
   const cacheMinutes = process.env.RENOVATE_CACHE_NPM_MINUTES
@@ -193,6 +197,9 @@ export async function getDependency(
       ) {
         release.sourceDirectory = source.sourceDirectory;
       }
+      if (dep.deprecationMessage) {
+        release.isDeprecated = true;
+      }
       return release;
     });
     logger.trace({ dep }, 'dep');
@@ -202,7 +209,7 @@ export async function getDependency(
       regEx(/(^|,)\s*public\s*(,|$)/).test(cacheControl)
     ) {
       dep.isPrivate = false;
-      const cacheData = { softExpireAt, etag };
+      const cacheData = { revision: CACHE_REVISION, softExpireAt, etag };
       await packageCache.set(
         cacheNamespace,
         packageUrl,
diff --git a/lib/modules/datasource/npm/types.ts b/lib/modules/datasource/npm/types.ts
index e67dd987a0e0efb7ca92085ae035b44b973028ad..2cd011d84bc072f292dedbb149ce7aa046366a52 100644
--- a/lib/modules/datasource/npm/types.ts
+++ b/lib/modules/datasource/npm/types.ts
@@ -35,6 +35,7 @@ export interface NpmResponse {
 
 export interface CachedReleaseResult extends ReleaseResult {
   cacheData?: {
+    revision?: number;
     etag: string | undefined;
     softExpireAt: string;
   };
diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts
index c4310a3444a4890fbae091b326ab20d1f82031e2..e56be9918897ad0501b636d49f7039a5df9cc59e 100644
--- a/lib/workers/repository/process/lookup/index.spec.ts
+++ b/lib/workers/repository/process/lookup/index.spec.ts
@@ -3154,13 +3154,16 @@ describe('workers/repository/process/lookup/index', () => {
       });
     });
 
-    it('ignores deprecated', async () => {
+    it('ignores deprecated when it is not the latest', async () => {
       config.currentValue = '1.3.0';
       config.packageName = 'q2';
       config.datasource = NpmDatasource.id;
       const returnJson = JSON.parse(JSON.stringify(qJson));
       returnJson.name = 'q2';
+      // mark latest minor as deprecated
       returnJson.versions['1.4.1'].deprecated = 'true';
+      // make sure latest release isn't the one deprecated as otherwise every release is deprecated
+      returnJson['dist-tags'].latest = '2.0.3';
       httpMock
         .scope('https://registry.npmjs.org')
         .get('/q2')
@@ -3169,16 +3172,8 @@ describe('workers/repository/process/lookup/index', () => {
       const res = await Result.wrap(
         lookup.lookupUpdates(config),
       ).unwrapOrThrow();
-
       expect(res).toEqual({
         currentVersion: '1.3.0',
-        deprecationMessage: codeBlock`
-          On registry \`https://registry.npmjs.org\`, the "latest" version of dependency \`q2\` has the following deprecation notice:
-
-          \`true\`
-
-          Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.
-        `,
         fixedVersion: '1.3.0',
         isSingleVersion: true,
         registryUrl: 'https://registry.npmjs.org',
@@ -3193,13 +3188,22 @@ describe('workers/repository/process/lookup/index', () => {
             releaseTimestamp: expect.any(String),
             updateType: 'minor',
           },
+          {
+            bucket: 'major',
+            newMajor: 2,
+            newMinor: 0,
+            newValue: '2.0.3',
+            newVersion: '2.0.3',
+            releaseTimestamp: expect.any(String),
+            updateType: 'major',
+          },
         ],
         versioning: 'npm',
         warnings: [],
       });
     });
 
-    it('is deprecated', async () => {
+    it('treats all versions as deprecated if latest is deprecated', async () => {
       config.currentValue = '1.3.0';
       config.packageName = 'q3';
       config.datasource = NpmDatasource.id;
@@ -3209,6 +3213,7 @@ describe('workers/repository/process/lookup/index', () => {
         deprecated: true,
         repository: { url: null, directory: 'test' },
       };
+      returnJson.versions['1.4.1'].deprecated = 'true';
 
       httpMock
         .scope('https://registry.npmjs.org')
@@ -3221,6 +3226,13 @@ describe('workers/repository/process/lookup/index', () => {
 
       expect(res).toEqual({
         currentVersion: '1.3.0',
+        deprecationMessage: codeBlock`
+        On registry \`https://registry.npmjs.org\`, the "latest" version of dependency \`q3\` has the following deprecation notice:
+
+        \`true\`
+
+        Marking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.
+      `,
         fixedVersion: '1.3.0',
         isSingleVersion: true,
         registryUrl: 'https://registry.npmjs.org',