diff --git a/src/vs/platform/update/common/update.ts b/src/vs/platform/update/common/update.ts
index 199f433..a6cbb10 100644
--- a/src/vs/platform/update/common/update.ts
+++ b/src/vs/platform/update/common/update.ts
@@ -51,3 +51,4 @@ export const enum UpdateType {
 	Archive,
-	Snap
+	Snap,
+	WindowsInstaller,
 }
@@ -110 +111,38 @@ export interface IUpdateService {
 }
+
+export type Architecture =
+	| "arm"
+	| "arm64"
+	| "ia32"
+	| "loong64"
+	| "mips"
+	| "mipsel"
+	| "ppc"
+	| "ppc64"
+	| "riscv64"
+	| "s390"
+	| "s390x"
+	| "x64";
+
+export type Platform =
+	| "aix"
+	| "android"
+	| "darwin"
+	| "freebsd"
+	| "haiku"
+	| "linux"
+	| "openbsd"
+	| "sunos"
+	| "win32"
+	| "cygwin"
+	| "netbsd";
+
+export type Quality =
+	| "insider"
+	| "stable";
+
+export type Target =
+	| "archive"
+	| "msi"
+	| "system"
+	| "user";
\ No newline at end of file
diff --git a/src/vs/platform/update/electron-main/abstractUpdateService.ts b/src/vs/platform/update/electron-main/abstractUpdateService.ts
index 48d0d86..840b9d3 100644
--- a/src/vs/platform/update/electron-main/abstractUpdateService.ts
+++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts
@@ -14,6 +14,10 @@ import { IProductService } from '../../product/common/productService.js';
 import { IRequestService } from '../../request/common/request.js';
-import { AvailableForDownload, DisablementReason, IUpdateService, State, StateType, UpdateType } from '../common/update.js';
+import { Architecture, AvailableForDownload, DisablementReason, IUpdateService, Platform, State, StateType, Target, UpdateType } from '../common/update.js';
 
-export function createUpdateURL(platform: string, quality: string, productService: IProductService): string {
-	return `${productService.updateUrl}/api/update/${platform}/${quality}/${productService.commit}`;
+export function createUpdateURL(productService: IProductService, quality: string, platform: Platform, architecture: Architecture, target?: Target): string {
+	if (target) {
+		return `${productService.updateUrl}/${quality}/${platform}/${architecture}/${target}/latest.json`;
+	} else {
+		return `${productService.updateUrl}/${quality}/${platform}/${architecture}/latest.json`;
+	}
 }
diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts
index b78ebc5..a4a3b1d 100644
--- a/src/vs/platform/update/electron-main/updateService.darwin.ts
+++ b/src/vs/platform/update/electron-main/updateService.darwin.ts
@@ -15,3 +15,3 @@ import { ILogService } from '../../log/common/log.js';
 import { IProductService } from '../../product/common/productService.js';
-import { IRequestService } from '../../request/common/request.js';
+import { IRequestService, asJson } from '../../request/common/request.js';
 import { ITelemetryService } from '../../telemetry/common/telemetry.js';
@@ -19,2 +19,4 @@ import { IUpdate, State, StateType, UpdateType } from '../common/update.js';
 import { AbstractUpdateService, createUpdateURL, UpdateErrorClassification } from './abstractUpdateService.js';
+import { CancellationToken } from '../../../base/common/cancellation.js';
+import * as semver from 'semver';
 
@@ -76,17 +78,3 @@ export class DarwinUpdateService extends AbstractUpdateService implements IRelau
 	protected buildUpdateFeedUrl(quality: string): string | undefined {
-		let assetID: string;
-		if (!this.productService.darwinUniversalAssetId) {
-			assetID = process.arch === 'x64' ? 'darwin' : 'darwin-arm64';
-		} else {
-			assetID = this.productService.darwinUniversalAssetId;
-		}
-		const url = createUpdateURL(assetID, quality, this.productService);
-		try {
-			electron.autoUpdater.setFeedURL({ url });
-		} catch (e) {
-			// application is very likely not signed
-			this.logService.error('Failed to set update feed URL', e);
-			return undefined;
-		}
-		return url;
+		return createUpdateURL(this.productService, quality, process.platform, process.arch);
 	}
@@ -100,5 +88,30 @@ export class DarwinUpdateService extends AbstractUpdateService implements IRelau
 
-		const url = explicit ? this.url : `${this.url}?bg=true`;
-		electron.autoUpdater.setFeedURL({ url });
-		electron.autoUpdater.checkForUpdates();
+		this.requestService.request({ url: this.url }, CancellationToken.None)
+			.then<IUpdate | null>(asJson)
+			.then(update => {
+				if (!update || !update.url || !update.version || !update.productVersion) {
+					this.setState(State.Idle(UpdateType.Setup));
+
+					return Promise.resolve(null);
+				}
+
+				const fetchedVersion = /\d+\.\d+\.\d+\.\d+/.test(update.productVersion) ? update.productVersion.replace(/(\d+\.\d+\.\d+)\.\d+(\-\w+)?/, '$1$2') : update.productVersion.replace(/(\d+\.\d+\.)0+(\d+)(\-\w+)?/, '$1$2$3')
+				const currentVersion = this.productService.version.replace(/(\d+\.\d+\.)0+(\d+)(\-\w+)?/, '$1$2$3')
+
+				if(semver.compareBuild(currentVersion, fetchedVersion) >= 0) {
+					this.setState(State.Idle(UpdateType.Setup));
+				}
+				else {
+					electron.autoUpdater.setFeedURL({ url: this.url! });
+					electron.autoUpdater.checkForUpdates();
+				}
+
+				return Promise.resolve(null);
+			})
+			.then(undefined, err => {
+				this.logService.error(err);
+				// only show message when explicitly checking for updates
+				const message: string | undefined = explicit ? (err.message || err) : undefined;
+				this.setState(State.Idle(UpdateType.Setup, message));
+			});
 	}
diff --git a/src/vs/platform/update/electron-main/updateService.linux.ts b/src/vs/platform/update/electron-main/updateService.linux.ts
index 8550ace..c2fddcb 100644
--- a/src/vs/platform/update/electron-main/updateService.linux.ts
+++ b/src/vs/platform/update/electron-main/updateService.linux.ts
@@ -15,2 +15,3 @@ import { AvailableForDownload, IUpdate, State, UpdateType } from '../common/upda
 import { AbstractUpdateService, createUpdateURL } from './abstractUpdateService.js';
+import * as semver from 'semver';
 
@@ -31,3 +32,3 @@ export class LinuxUpdateService extends AbstractUpdateService {
 	protected buildUpdateFeedUrl(quality: string): string {
-		return createUpdateURL(`linux-${process.arch}`, quality, this.productService);
+		return createUpdateURL(this.productService, quality, process.platform, process.arch);
 	}
@@ -39,6 +40,5 @@ export class LinuxUpdateService extends AbstractUpdateService {
 
-		const url = explicit ? this.url : `${this.url}?bg=true`;
 		this.setState(State.CheckingForUpdates(explicit));
 
-		this.requestService.request({ url }, CancellationToken.None)
+		this.requestService.request({ url: this.url }, CancellationToken.None)
 			.then<IUpdate | null>(asJson)
@@ -47,5 +47,17 @@ export class LinuxUpdateService extends AbstractUpdateService {
 					this.setState(State.Idle(UpdateType.Archive));
-				} else {
+
+					return Promise.resolve(null);
+				}
+
+				const fetchedVersion = /\d+\.\d+\.\d+\.\d+/.test(update.productVersion) ? update.productVersion.replace(/(\d+\.\d+\.\d+)\.\d+(\-\w+)?/, '$1$2') : update.productVersion.replace(/(\d+\.\d+\.)0+(\d+)(\-\w+)?/, '$1$2$3')
+				const currentVersion = this.productService.version.replace(/(\d+\.\d+\.)0+(\d+)(\-\w+)?/, '$1$2$3')
+
+				if(semver.compareBuild(currentVersion, fetchedVersion) >= 0) {
+					this.setState(State.Idle(UpdateType.Archive));
+				}
+				else {
 					this.setState(State.AvailableForDownload(update));
 				}
+
+				return Promise.resolve(null);
 			})
diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts
index 8f92a3e..020e690 100644
--- a/src/vs/platform/update/electron-main/updateService.win32.ts
+++ b/src/vs/platform/update/electron-main/updateService.win32.ts
@@ -11,3 +11,2 @@ import { CancellationToken } from '../../../base/common/cancellation.js';
 import { memoize } from '../../../base/common/decorators.js';
-import { hash } from '../../../base/common/hash.js';
 import * as path from '../../../base/common/path.js';
@@ -25,4 +24,5 @@ import { asJson, IRequestService } from '../../request/common/request.js';
 import { ITelemetryService } from '../../telemetry/common/telemetry.js';
-import { AvailableForDownload, DisablementReason, IUpdate, State, StateType, UpdateType } from '../common/update.js';
-import { AbstractUpdateService, createUpdateURL, UpdateErrorClassification } from './abstractUpdateService.js';
+import { AvailableForDownload, DisablementReason, IUpdate, State, StateType, Target, UpdateType } from '../common/update.js';
+import { AbstractUpdateService, createUpdateURL} from './abstractUpdateService.js';
+import * as semver from 'semver';
 
@@ -42,5 +42,9 @@ function getUpdateType(): UpdateType {
 	if (typeof _updateType === 'undefined') {
-		_updateType = fs.existsSync(path.join(path.dirname(process.execPath), 'unins000.exe'))
-			? UpdateType.Setup
-			: UpdateType.Archive;
+		if (fs.existsSync(path.join(path.dirname(process.execPath), 'unins000.exe'))) {
+			_updateType = UpdateType.Setup;
+		} else if (path.basename(path.normalize(path.join(process.execPath, '..', '..'))) === 'Program Files') {
+			_updateType = UpdateType.WindowsInstaller;
+		} else {
+			_updateType = UpdateType.Archive;
+		}
 	}
@@ -63,2 +67,3 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 		@IConfigurationService configurationService: IConfigurationService,
+		// @ts-expect-error
 		@ITelemetryService private readonly telemetryService: ITelemetryService,
@@ -102,11 +107,21 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 	protected buildUpdateFeedUrl(quality: string): string | undefined {
-		let platform = `win32-${process.arch}`;
-
-		if (getUpdateType() === UpdateType.Archive) {
-			platform += '-archive';
-		} else if (this.productService.target === 'user') {
-			platform += '-user';
+		let target: Target;
+
+		switch (getUpdateType()) {
+			case UpdateType.Archive:
+				target = "archive"
+				break;
+			case UpdateType.WindowsInstaller:
+				target = "msi"
+				break;
+			default:
+				if (this.productService.target === 'user') {
+					target = "user"
+				}
+				else {
+					target = "system"
+				}
 		}
 
-		return createUpdateURL(platform, quality, this.productService);
+		return createUpdateURL(this.productService, quality, process.platform, process.arch, target);
 	}
@@ -131,2 +146,10 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 
+				const fetchedVersion = /\d+\.\d+\.\d+\.\d+/.test(update.productVersion) ? update.productVersion.replace(/(\d+\.\d+\.\d+)\.\d+(\-\w+)?/, '$1$2') : update.productVersion.replace(/(\d+\.\d+\.)0+(\d+)(\-\w+)?/, '$1$2$3')
+				const currentVersion = this.productService.version.replace(/(\d+\.\d+\.)0+(\d+)(\-\w+)?/, '$1$2$3')
+
+				if(semver.compareBuild(currentVersion, fetchedVersion) >= 0) {
+					this.setState(State.Idle(updateType));
+					return Promise.resolve(null);
+				}
+
 				if (updateType === UpdateType.Archive) {
@@ -157,3 +180,3 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 
-						const fastUpdatesEnabled = this.configurationService.getValue('update.enableWindowsBackgroundUpdates');
+						const fastUpdatesEnabled = getUpdateType() == UpdateType.Setup && this.configurationService.getValue('update.enableWindowsBackgroundUpdates');
 						if (fastUpdatesEnabled) {
@@ -169,3 +192,2 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 			.then(undefined, err => {
-				this.telemetryService.publicLog2<{ messageHash: string }, UpdateErrorClassification>('update:error', { messageHash: String(hash(String(err))) });
 				this.logService.error(err);
@@ -253,6 +275,14 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 		} else {
-			spawn(this.availableUpdate.packagePath, ['/silent', '/log', '/mergetasks=runcode,!desktopicon,!quicklaunchicon'], {
-				detached: true,
-				stdio: ['ignore', 'ignore', 'ignore']
-			});
+			const type = getUpdateType();
+			if (type == UpdateType.WindowsInstaller) {
+				spawn('msiexec.exe', ['/i', this.availableUpdate.packagePath], {
+					detached: true,
+					stdio: ['ignore', 'ignore', 'ignore']
+				});
+			} else {
+				spawn(this.availableUpdate.packagePath, ['/silent', '/log', '/mergetasks=runcode,!desktopicon,!quicklaunchicon'], {
+					detached: true,
+					stdio: ['ignore', 'ignore', 'ignore']
+				});
+			}
 		}
