diff --git a/.changeset/early-deers-suffer.md b/.changeset/early-deers-suffer.md
new file mode 100644
index 00000000000..1d73dc6ccad
--- /dev/null
+++ b/.changeset/early-deers-suffer.md
@@ -0,0 +1,5 @@
+---
+"app-builder-lib": minor
+---
+
+feat: allow disabling of building a universal windows installer
diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json
index 0d9e91e0b1c..7797f45e3d5 100644
--- a/packages/app-builder-lib/scheme.json
+++ b/packages/app-builder-lib/scheme.json
@@ -3900,6 +3900,11 @@
             "string"
           ]
         },
+        "buildUniversalInstaller": {
+          "default": true,
+          "description": "Disable building an universal installer of the archs specified in the target configuration\n*Not supported for nsis-web*",
+          "type": "boolean"
+        },
         "createDesktopShortcut": {
           "default": true,
           "description": "Whether to create desktop shortcut. Set to `always` if to recreate also on reinstall (even if removed by user).",
@@ -4200,6 +4205,11 @@
             "string"
           ]
         },
+        "buildUniversalInstaller": {
+          "default": true,
+          "description": "Disable building an universal installer of the archs specified in the target configuration\n*Not supported for nsis-web*",
+          "type": "boolean"
+        },
         "createDesktopShortcut": {
           "default": true,
           "description": "Whether to create desktop shortcut. Set to `always` if to recreate also on reinstall (even if removed by user).",
diff --git a/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts b/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts
index 27f26b42285..d8e7a06f095 100644
--- a/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts
+++ b/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts
@@ -1,5 +1,18 @@
 import BluebirdPromise from "bluebird-lst"
-import { Arch, asArray, AsyncTaskManager, exec, executeAppBuilder, getPlatformIconFileName, InvalidConfigurationError, log, spawnAndWrite, use, getPath7za } from "builder-util"
+import {
+  Arch,
+  asArray,
+  AsyncTaskManager,
+  exec,
+  executeAppBuilder,
+  getPlatformIconFileName,
+  InvalidConfigurationError,
+  log,
+  spawnAndWrite,
+  use,
+  getPath7za,
+  getArchSuffix,
+} from "builder-util"
 import { CURRENT_APP_INSTALLER_FILE_NAME, CURRENT_APP_PACKAGE_FILE_NAME, PackageFileInfo, UUID } from "builder-util-runtime"
 import { exists, statOrNull, walk } from "builder-util"
 import _debug from "debug"
@@ -9,7 +22,7 @@ import * as path from "path"
 import { getBinFromUrl } from "../../binDownload"
 import { Target } from "../../core"
 import { DesktopShortcutCreationPolicy, getEffectiveOptions } from "../../options/CommonWindowsInstallerConfiguration"
-import { computeSafeArtifactNameIfNeeded, normalizeExt } from "../../platformPackager"
+import { chooseNotNull, computeSafeArtifactNameIfNeeded, normalizeExt } from "../../platformPackager"
 import { hashFile } from "../../util/hash"
 import { isMacOsCatalina } from "../../util/macosVersion"
 import { time } from "../../util/timer"
@@ -73,8 +86,16 @@ export class NsisTarget extends Target {
     NsisTargetOptions.resolve(this.options)
   }
 
+  get shouldBuildUniversalInstaller() {
+    const buildSeparateInstallers = this.options.buildUniversalInstaller === false
+    return !buildSeparateInstallers
+  }
+
   build(appOutDir: string, arch: Arch) {
     this.archs.set(arch, appOutDir)
+    if (!this.shouldBuildUniversalInstaller) {
+      return this.buildInstaller(new Map<Arch, string>().set(arch, appOutDir))
+    }
     return Promise.resolve()
   }
 
@@ -117,9 +138,11 @@ export class NsisTarget extends Target {
     }
   }
 
-  protected get installerFilenamePattern(): string {
-    // tslint:disable:no-invalid-template-strings
-    return "${productName} " + (this.isPortable ? "" : "Setup ") + "${version}.${ext}"
+  protected installerFilenamePattern(primaryArch?: Arch | null, defaultArch?: string): string {
+    const setupText = this.isPortable ? "" : "Setup "
+    const archSuffix = !this.shouldBuildUniversalInstaller && primaryArch != null ? getArchSuffix(primaryArch, defaultArch) : ""
+
+    return "${productName} " + setupText + "${version}" + archSuffix + ".${ext}";
   }
 
   private get isPortable(): boolean {
@@ -127,8 +150,11 @@ export class NsisTarget extends Target {
   }
 
   async finishBuild(): Promise<any> {
+    if (!this.shouldBuildUniversalInstaller) {
+      return this.packageHelper.finishBuild()
+    }
     try {
-      const { pattern } = this.packager.artifactPatternConfig(this.options, this.installerFilenamePattern)
+      const { pattern } = this.packager.artifactPatternConfig(this.options, this.installerFilenamePattern())
       const builds = new Set([this.archs])
       if (pattern.includes("${arch}") && this.archs.size > 1) {
         ;[...this.archs].forEach(([arch, appOutDir]) => builds.add(new Map().set(arch, appOutDir)))
@@ -147,14 +173,8 @@ export class NsisTarget extends Target {
     const packager = this.packager
     const appInfo = packager.appInfo
     const options = this.options
-    const installerFilename = packager.expandArtifactNamePattern(
-      options,
-      "exe",
-      primaryArch,
-      this.installerFilenamePattern,
-      false,
-      this.packager.platformSpecificBuildOptions.defaultArch
-    )
+    const defaultArch = chooseNotNull(this.packager.platformSpecificBuildOptions.defaultArch, this.packager.config.defaultArch) ?? undefined
+    const installerFilename = packager.expandArtifactNamePattern(options, "exe", primaryArch, this.installerFilenamePattern(primaryArch, defaultArch), false, defaultArch)
     const oneClick = options.oneClick !== false
     const installerPath = path.join(this.outDir, installerFilename)
 
@@ -328,7 +348,7 @@ export class NsisTarget extends Target {
     await this.executeMakensis(defines, commands, sharedHeader + (await this.computeFinalScript(script, true, archs)))
     await Promise.all<any>([packager.sign(installerPath), defines.UNINSTALLER_OUT_FILE == null ? Promise.resolve() : unlink(defines.UNINSTALLER_OUT_FILE)])
 
-    const safeArtifactName = computeSafeArtifactNameIfNeeded(installerFilename, () => this.generateGitHubInstallerName())
+    const safeArtifactName = computeSafeArtifactNameIfNeeded(installerFilename, () => this.generateGitHubInstallerName(primaryArch, defaultArch))
     let updateInfo: any
     if (this.isWebInstaller) {
       updateInfo = createNsisWebDifferentialUpdateInfo(installerPath, packageFiles)
@@ -351,10 +371,11 @@ export class NsisTarget extends Target {
     })
   }
 
-  protected generateGitHubInstallerName(): string {
+  protected generateGitHubInstallerName(primaryArch: Arch | null, defaultArch: string | undefined): string {
     const appInfo = this.packager.appInfo
     const classifier = appInfo.name.toLowerCase() === appInfo.name ? "setup-" : "Setup-"
-    return `${appInfo.name}-${this.isPortable ? "" : classifier}${appInfo.version}.exe`
+    const archSuffix = !this.shouldBuildUniversalInstaller && primaryArch != null ? getArchSuffix(primaryArch, defaultArch) : ""
+    return `${appInfo.name}-${this.isPortable ? "" : classifier}${appInfo.version}${archSuffix}.exe`
   }
 
   private get isUnicodeEnabled(): boolean {
diff --git a/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts b/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts
index f8311c3f231..cad495bdc36 100644
--- a/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts
+++ b/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts
@@ -1,3 +1,4 @@
+import { Arch, log } from "builder-util"
 import { computeDownloadUrl, getPublishConfigs, getPublishConfigsForUpdateInfo } from "../../publish/PublishManager"
 import { WinPackager } from "../../winPackager"
 import { NsisWebOptions } from "./nsisOptions"
@@ -35,8 +36,14 @@ export class WebInstallerTarget extends NsisTarget {
     defines.APP_PACKAGE_URL = appPackageUrl
   }
 
-  protected get installerFilenamePattern(): string {
-    // tslint:disable:no-invalid-template-strings
+  get shouldBuildUniversalInstaller() {
+    if (this.options.buildUniversalInstaller === false) {
+      log.warn({ buildUniversalInstaller: true }, "only universal builds are supported for nsis-web installers, overriding setting")
+    }
+    return true
+  }
+
+  protected installerFilenamePattern(_primaryArch?: Arch | null, _defaultArch?: string): string {
     return "${productName} Web Setup ${version}.${ext}"
   }
 
diff --git a/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts b/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts
index d6f24b47d3c..7bf2cf47ba8 100644
--- a/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts
+++ b/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts
@@ -198,6 +198,13 @@ export interface NsisOptions extends CommonNsisOptions, CommonWindowsInstallerCo
    * @default [".avi", ".mov", ".m4v", ".mp4", ".m4p", ".qt", ".mkv", ".webm", ".vmdk"]
    */
   readonly preCompressedFileExtensions?: Array<string> | string | null
+
+  /**
+   * Disable building an universal installer of the archs specified in the target configuration
+   * *Not supported for nsis-web*
+   * @default true
+   */
+  readonly buildUniversalInstaller?: boolean
 }
 
 /**
diff --git a/test/snapshots/windows/webInstallerTest.js.snap b/test/snapshots/windows/webInstallerTest.js.snap
index dd883921a39..9c798881b27 100644
--- a/test/snapshots/windows/webInstallerTest.js.snap
+++ b/test/snapshots/windows/webInstallerTest.js.snap
@@ -99,6 +99,13 @@ exports[`web installer 1`] = `
           },
         ],
         "packages": {
+          "arm64": {
+            "blockMapSize": "@blockMapSize",
+            "file": "TestApp-1.1.0-arm64.nsis.7z",
+            "path": "TestApp-1.1.0-arm64.nsis.7z",
+            "sha512": "@sha512",
+            "size": "@size",
+          },
           "x64": {
             "blockMapSize": "@blockMapSize",
             "file": "TestApp-1.1.0-x64.nsis.7z",
@@ -114,11 +121,17 @@ exports[`web installer 1`] = `
       },
     },
     {
-      "arch": "x64",
       "file": "Test App ßW Web Setup 1.1.0.exe",
       "safeArtifactName": "TestApp-WebSetup-1.1.0.exe",
       "updateInfo": {
         "packages": {
+          "arm64": {
+            "blockMapSize": "@blockMapSize",
+            "file": "TestApp-1.1.0-arm64.nsis.7z",
+            "path": "TestApp-1.1.0-arm64.nsis.7z",
+            "sha512": "@sha512",
+            "size": "@size",
+          },
           "x64": {
             "blockMapSize": "@blockMapSize",
             "file": "TestApp-1.1.0-x64.nsis.7z",
@@ -129,6 +142,10 @@ exports[`web installer 1`] = `
         },
       },
     },
+    {
+      "arch": "arm64",
+      "file": "TestApp-1.1.0-arm64.nsis.7z",
+    },
     {
       "arch": "x64",
       "file": "TestApp-1.1.0-x64.nsis.7z",
diff --git a/test/snapshots/windows/winPackagerTest.js.snap b/test/snapshots/windows/winPackagerTest.js.snap
index 7d91d846471..8dbb4228081 100644
--- a/test/snapshots/windows/winPackagerTest.js.snap
+++ b/test/snapshots/windows/winPackagerTest.js.snap
@@ -3,6 +3,23 @@
 exports[`beta version 1`] = `
 {
   "win": [
+    {
+      "arch": "arm64",
+      "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe",
+      "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe",
+      "updateInfo": {
+        "sha512": "@sha512",
+        "size": "@size",
+      },
+    },
+    {
+      "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe.blockmap",
+      "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe.blockmap",
+      "updateInfo": {
+        "sha512": "@sha512",
+        "size": "@size",
+      },
+    },
     {
       "arch": "x64",
       "file": "Test App ßW Setup 3.0.0-beta.2.exe",
@@ -31,6 +48,11 @@ exports[`icon not an image 1`] = `"ERR_ICON_UNKNOWN_FORMAT"`;
 exports[`win zip 1`] = `
 {
   "win": [
+    {
+      "arch": "arm64",
+      "file": "Test App ßW-1.1.0-arm64-win.zip",
+      "safeArtifactName": "TestApp-1.1.0-arm64-win.zip",
+    },
     {
       "arch": "x64",
       "file": "Test App ßW-1.1.0-win.zip",
diff --git a/test/src/windows/webInstallerTest.ts b/test/src/windows/webInstallerTest.ts
index 5e11f605e62..62492797156 100644
--- a/test/src/windows/webInstallerTest.ts
+++ b/test/src/windows/webInstallerTest.ts
@@ -6,7 +6,7 @@ import { app } from "../helpers/packTester"
 test.ifNotCiMac(
   "web installer",
   app({
-    targets: Platform.WINDOWS.createTarget(["nsis-web"], Arch.x64),
+    targets: Platform.WINDOWS.createTarget(["nsis-web"], Arch.x64, Arch.arm64),
     config: {
       publish: {
         provider: "s3",
@@ -23,6 +23,9 @@ test.ifNotCiMac(
         loadBrowserProcessSpecificV8Snapshot: true,
         grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests
       },
+      nsisWeb: {
+        buildUniversalInstaller: false,
+      },
     },
   })
 )
diff --git a/test/src/windows/winPackagerTest.ts b/test/src/windows/winPackagerTest.ts
index 79a47da5c1e..a776d2af48a 100644
--- a/test/src/windows/winPackagerTest.ts
+++ b/test/src/windows/winPackagerTest.ts
@@ -4,14 +4,17 @@ import { CheckingWinPackager } from "../helpers/CheckingPackager"
 import { app, appThrows, assertPack, platform } from "../helpers/packTester"
 import * as fs from "fs/promises"
 
-test.ifWinCi(
+test.ifNotCiMac(
   "beta version",
   app({
-    targets: Platform.WINDOWS.createTarget(["nsis"], Arch.x64),
+    targets: Platform.WINDOWS.createTarget(["nsis"], Arch.x64, Arch.arm64),
     config: {
       extraMetadata: {
         version: "3.0.0-beta.2",
       },
+      nsis: {
+        buildUniversalInstaller: false,
+      },
     },
   })
 )
@@ -19,7 +22,7 @@ test.ifWinCi(
 test.ifNotCiMac(
   "win zip",
   app({
-    targets: Platform.WINDOWS.createTarget(["zip"], Arch.x64),
+    targets: Platform.WINDOWS.createTarget(["zip"], Arch.x64, Arch.arm64),
     config: {
       downloadAlternateFFmpeg: true,
       electronFuses: {