diff --git a/lib/modules/versioning/index.spec.ts b/lib/modules/versioning/index.spec.ts
index 9fe12ce0d6c38df71470f3a5f37f6c3e079f6f6c..017d198e1b4af1a2b43907d6e6f13ea0f6581e78 100644
--- a/lib/modules/versioning/index.spec.ts
+++ b/lib/modules/versioning/index.spec.ts
@@ -73,6 +73,7 @@ describe('modules/versioning/index', () => {
 
   describe('should return the same interface', () => {
     const optionalFunctions = [
+      'allowUnstableMajorUpgrades',
       'isLessThanRange',
       'valueToVersion',
       'constructor',
diff --git a/lib/modules/versioning/node/index.ts b/lib/modules/versioning/node/index.ts
index d243a4425982a2530d0460e11aee315d099339f1..35eb921153862552d0a94395406433264c518cda 100644
--- a/lib/modules/versioning/node/index.ts
+++ b/lib/modules/versioning/node/index.ts
@@ -85,6 +85,7 @@ export const api: VersioningApi = {
   matches,
   getSatisfyingVersion,
   minSatisfyingVersion,
+  allowUnstableMajorUpgrades: true,
 };
 
 export default api;
diff --git a/lib/modules/versioning/types.ts b/lib/modules/versioning/types.ts
index a1808b08cb1c4516b5877012c12821bc70af8c00..6c9807d7c30e6c669572cd5369d647132067636d 100644
--- a/lib/modules/versioning/types.ts
+++ b/lib/modules/versioning/types.ts
@@ -106,6 +106,11 @@ export interface VersioningApi {
    * @param superRange - the dom range
    */
   subset?(subRange: string, superRange: string): boolean | undefined;
+
+  /**
+   * Return whether unstable-to-unstable upgrades within the same major version are allowed.
+   */
+  allowUnstableMajorUpgrades?: boolean;
 }
 
 export interface VersioningApiConstructor {
diff --git a/lib/workers/repository/process/lookup/filter.ts b/lib/workers/repository/process/lookup/filter.ts
index 50d1959f0df3dbaea3b90a8962b6132dfa5c5e7d..e94cfbca158e2f7bfc744c4e0111a7970a8bf20c 100644
--- a/lib/workers/repository/process/lookup/filter.ts
+++ b/lib/workers/repository/process/lookup/filter.ts
@@ -131,12 +131,21 @@ export function filterVersions(
 
   // if current is unstable then allow unstable in the current major only
   // Allow unstable only in current major
-  return filteredVersions.filter(
-    (v) =>
-      isVersionStable(v.version) ||
-      (versioning.getMajor(v.version) === versioning.getMajor(currentVersion) &&
-        versioning.getMinor(v.version) ===
-          versioning.getMinor(currentVersion) &&
-        versioning.getPatch(v.version) === versioning.getPatch(currentVersion))
-  );
+  return filteredVersions.filter((v) => {
+    if (isVersionStable(v.version)) {
+      return true;
+    }
+    if (
+      versioning.getMajor(v.version) !== versioning.getMajor(currentVersion)
+    ) {
+      return false;
+    }
+    if (versioning.allowUnstableMajorUpgrades) {
+      return true;
+    }
+    return (
+      versioning.getMinor(v.version) === versioning.getMinor(currentVersion) &&
+      versioning.getPatch(v.version) === versioning.getPatch(currentVersion)
+    );
+  });
 }
diff --git a/lib/workers/repository/process/lookup/index.spec.ts b/lib/workers/repository/process/lookup/index.spec.ts
index 6a3122b53838c5e5018a3a4ffec838bc88f950b5..473179f0186995835a55178ef8fecfb8fe85d7b9 100644
--- a/lib/workers/repository/process/lookup/index.spec.ts
+++ b/lib/workers/repository/process/lookup/index.spec.ts
@@ -13,6 +13,7 @@ import { PackagistDatasource } from '../../../../modules/datasource/packagist';
 import { PypiDatasource } from '../../../../modules/datasource/pypi';
 import { id as dockerVersioningId } from '../../../../modules/versioning/docker';
 import { id as gitVersioningId } from '../../../../modules/versioning/git';
+import { id as nodeVersioningId } from '../../../../modules/versioning/node';
 import { id as npmVersioningId } from '../../../../modules/versioning/npm';
 import { id as pep440VersioningId } from '../../../../modules/versioning/pep440';
 import { id as poetryVersioningId } from '../../../../modules/versioning/poetry';
@@ -45,6 +46,11 @@ describe('workers/repository/process/lookup/index', () => {
     'getReleases'
   );
 
+  const getGithubTags = jest.spyOn(
+    GithubTagsDatasource.prototype,
+    'getReleases'
+  );
+
   const getDockerReleases = jest.spyOn(
     DockerDatasource.prototype,
     'getReleases'
@@ -999,6 +1005,23 @@ describe('workers/repository/process/lookup/index', () => {
       ]);
     });
 
+    it('should allow unstable versions in same major for node', async () => {
+      config.currentValue = '20.3.0';
+      config.packageName = 'node';
+      config.datasource = GithubTagsDatasource.id;
+      config.versioning = nodeVersioningId;
+      getGithubTags.mockResolvedValueOnce({
+        releases: [
+          { version: '20.3.0' },
+          { version: '20.3.1' },
+          { version: '21.0.0' },
+        ],
+      });
+      expect((await lookup.lookupUpdates(config)).updates).toMatchObject([
+        { newValue: '20.3.1', updateType: 'patch' },
+      ]);
+    });
+
     it('should return pendingChecks', async () => {
       config.currentValue = '1.4.4';
       config.packageName = 'some/action';