diff --git a/src/vs/platform/update/common/update.ts b/src/vs/platform/update/common/update.ts
index bc90a03..f8885b9 100644
--- a/src/vs/platform/update/common/update.ts
+++ b/src/vs/platform/update/common/update.ts
@@ -54,3 +54,4 @@ export const enum UpdateType {
 	Archive,
-	Snap
+	Snap,
+	WindowsInstaller,
 }
@@ -120 +121,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 c943bca..1395594 100644
--- a/src/vs/platform/update/electron-main/abstractUpdateService.ts
+++ b/src/vs/platform/update/electron-main/abstractUpdateService.ts
@@ -17,4 +17,4 @@ import { ILogService } from '../../log/common/log.js';
 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 { IRequestService, NO_FETCH_TELEMETRY } from '../../request/common/request.js';
+import { Architecture, AvailableForDownload, DisablementReason, IUpdateService, Platform, State, StateType, Target, UpdateType } from '../common/update.js';
 
@@ -25,12 +25,8 @@ export interface IUpdateURLOptions {
 
-export function createUpdateURL(baseUpdateUrl: string, platform: string, quality: string, commit: string, options?: IUpdateURLOptions): string {
-	const url = new URL(`${baseUpdateUrl}/api/update/${platform}/${quality}/${commit}`);
-
-	if (options?.background) {
-		url.searchParams.set('bg', 'true');
+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`;
 	}
-
-	url.searchParams.set('u', options?.internalOrg ?? 'none');
-
-	return url.toString();
 }
@@ -322,3 +318,3 @@ export abstract class AbstractUpdateService implements IUpdateService {
 
-		if (mode === 'none') {
+		if (mode === 'none' || mode === 'manual') {
 			return undefined;
@@ -336,3 +332,3 @@ export abstract class AbstractUpdateService implements IUpdateService {
 		try {
-			const context = await this.requestService.request({ url, headers, callSite: 'updateService.isLatestVersion' }, token);
+			const context = await this.requestService.request({ url, headers, callSite: NO_FETCH_TELEMETRY }, token);
 			const statusCode = context.res.statusCode;
diff --git a/src/vs/platform/update/electron-main/updateService.darwin.ts b/src/vs/platform/update/electron-main/updateService.darwin.ts
index 40b38a2..323919e 100644
--- a/src/vs/platform/update/electron-main/updateService.darwin.ts
+++ b/src/vs/platform/update/electron-main/updateService.darwin.ts
@@ -16,3 +16,3 @@ import { ILogService } from '../../log/common/log.js';
 import { IProductService } from '../../product/common/productService.js';
-import { asJson, IRequestService } from '../../request/common/request.js';
+import { asJson, IRequestService, NO_FETCH_TELEMETRY } from '../../request/common/request.js';
 import { ITelemetryService } from '../../telemetry/common/telemetry.js';
@@ -22,2 +22,3 @@ import { AbstractUpdateService, createUpdateURL, getUpdateRequestHeaders, IUpdat
 import { INodeProcess } from '../../../base/common/platform.js';
+import * as semver from 'semver';
 
@@ -99,15 +100,4 @@ export class DarwinUpdateService extends AbstractUpdateService implements IRelau
 
-	protected buildUpdateFeedUrl(quality: string, commit: string, options?: IUpdateURLOptions): string | undefined {
-		const assetID = this.productService.darwinUniversalAssetId ?? (process.arch === 'x64' ? 'darwin' : 'darwin-arm64');
-		const url = createUpdateURL(this.productService.updateUrl!, assetID, quality, commit, options);
-		const headers = getUpdateRequestHeaders(this.productService.version);
-		try {
-			this.logService.trace('update#buildUpdateFeedUrl - setting feed URL for Electron autoUpdater', { url, assetID, quality, commit, headers });
-			electron.autoUpdater.setFeedURL({ url, headers });
-		} catch (e) {
-			// application is very likely not signed
-			this.logService.error('Failed to set update feed URL', e);
-			return undefined;
-		}
-		return url;
+	protected buildUpdateFeedUrl(quality: string, _commit: string, _options?: IUpdateURLOptions): string | undefined {
+		return createUpdateURL(this.productService, quality, process.platform, process.arch);
 	}
@@ -154,3 +144,30 @@ export class DarwinUpdateService extends AbstractUpdateService implements IRelau
 		this.logService.trace('update#doCheckForUpdates - using Electron autoUpdater', { url, explicit, background });
-		electron.autoUpdater.checkForUpdates();
+		this.requestService.request({ url, callSite: NO_FETCH_TELEMETRY }, CancellationToken.None)
+			.then<IUpdate | null>(asJson)
+			.then(update => {
+				if (!update || !update.url || !update.version || !update.productVersion) {
+					this.setState(State.Idle(UpdateType.Setup, undefined, explicit || undefined));
+
+					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, undefined, explicit || undefined));
+				}
+				else {
+					electron.autoUpdater.setFeedURL({ 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));
+			});
 	}
@@ -167,3 +184,3 @@ export class DarwinUpdateService extends AbstractUpdateService implements IRelau
 		try {
-			const context = await this.requestService.request({ url, headers, callSite: 'updateService.darwin.checkForUpdates' }, CancellationToken.None);
+			const context = await this.requestService.request({ url, headers, callSite: NO_FETCH_TELEMETRY }, CancellationToken.None);
 			const statusCode = context.res.statusCode;
diff --git a/src/vs/platform/update/electron-main/updateService.linux.ts b/src/vs/platform/update/electron-main/updateService.linux.ts
index 0eb5d74..8ce708e 100644
--- a/src/vs/platform/update/electron-main/updateService.linux.ts
+++ b/src/vs/platform/update/electron-main/updateService.linux.ts
@@ -13,5 +13,6 @@ import { INativeHostMainService } from '../../native/electron-main/nativeHostMai
 import { IProductService } from '../../product/common/productService.js';
-import { asJson, IRequestService } from '../../request/common/request.js';
+import { asJson, IRequestService, NO_FETCH_TELEMETRY } from '../../request/common/request.js';
 import { AvailableForDownload, IUpdate, State, UpdateType } from '../common/update.js';
 import { AbstractUpdateService, createUpdateURL, IUpdateURLOptions } from './abstractUpdateService.js';
+import * as semver from 'semver';
 
@@ -32,4 +33,4 @@ export class LinuxUpdateService extends AbstractUpdateService {
 
-	protected buildUpdateFeedUrl(quality: string, commit: string, options?: IUpdateURLOptions): string {
-		return createUpdateURL(this.productService.updateUrl!, `linux-${process.arch}`, quality, commit, options);
+	protected buildUpdateFeedUrl(quality: string, _commit: string, _options?: IUpdateURLOptions): string {
+		return createUpdateURL(this.productService, quality, process.platform, process.arch);
 	}
@@ -46,3 +47,3 @@ export class LinuxUpdateService extends AbstractUpdateService {
 
-		this.requestService.request({ url, callSite: 'updateService.linux.checkForUpdates' }, CancellationToken.None)
+		this.requestService.request({ url, callSite: NO_FETCH_TELEMETRY }, CancellationToken.None)
 			.then<IUpdate | null>(asJson)
@@ -51,5 +52,17 @@ export class LinuxUpdateService extends AbstractUpdateService {
 					this.setState(State.Idle(UpdateType.Archive, undefined, explicit || undefined));
-				} 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, undefined, explicit || undefined));
+				}
+				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 d02d7c3..4e8c541 100644
--- a/src/vs/platform/update/electron-main/updateService.win32.ts
+++ b/src/vs/platform/update/electron-main/updateService.win32.ts
@@ -14,3 +14,2 @@ import { CancellationToken, CancellationTokenSource } from '../../../base/common
 import { memoize } from '../../../base/common/decorators.js';
-import { hash } from '../../../base/common/hash.js';
 import * as path from '../../../base/common/path.js';
@@ -31,7 +30,8 @@ import { INativeHostMainService } from '../../native/electron-main/nativeHostMai
 import { IProductService } from '../../product/common/productService.js';
-import { asJson, IRequestService } from '../../request/common/request.js';
+import { asJson, IRequestService, NO_FETCH_TELEMETRY } 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, getUpdateRequestHeaders, IUpdateURLOptions, UpdateErrorClassification } from './abstractUpdateService.js';
+import { AvailableForDownload, DisablementReason, IUpdate, State, StateType, Target, UpdateType } from '../common/update.js';
+import { AbstractUpdateService, createUpdateURL, getUpdateRequestHeaders, IUpdateURLOptions } from './abstractUpdateService.js';
 import { INodeProcess } from '../../../base/common/platform.js';
+import * as semver from 'semver';
 
@@ -49,5 +49,9 @@ function getUpdateType(): UpdateType {
 	if (typeof _updateType === 'undefined') {
-		_updateType = existsSync(path.join(path.dirname(process.execPath), 'unins000.exe'))
-			? UpdateType.Setup
-			: UpdateType.Archive;
+		if (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;
+		}
 	}
@@ -164,3 +168,3 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 		} else {
-			const fastUpdatesEnabled = this.configurationService.getValue('update.enableWindowsBackgroundUpdates');
+			const fastUpdatesEnabled = getUpdateType() === UpdateType.Setup && this.configurationService.getValue('update.enableWindowsBackgroundUpdates');
 			// GC for background updates in system setup happens via inno_setup since it requires
@@ -182,12 +186,22 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 
-	protected buildUpdateFeedUrl(quality: string, commit: string, options?: IUpdateURLOptions): string | undefined {
-		let platform = `win32-${process.arch}`;
-
-		if (getUpdateType() === UpdateType.Archive) {
-			platform += '-archive';
-		} else if (this.productService.target === 'user') {
-			platform += '-user';
+	protected buildUpdateFeedUrl(quality: string, _commit: string, _options?: IUpdateURLOptions): string | undefined {
+		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(this.productService.updateUrl!, platform, quality, commit, options);
+		return createUpdateURL(this.productService, quality, process.platform, process.arch, target);
 	}
@@ -209,3 +223,3 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 		const headers = getUpdateRequestHeaders(this.productService.version);
-		this.requestService.request({ url, headers, callSite: 'updateService.win32.checkForUpdates' }, CancellationToken.None)
+		this.requestService.request({ url, headers, callSite: NO_FETCH_TELEMETRY }, CancellationToken.None)
 			.then<IUpdate | null>(asJson)
@@ -226,2 +240,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, undefined, explicit || undefined));
+					return Promise.resolve(null);
+				}
+
 				if (updateType === UpdateType.Archive) {
@@ -258,3 +280,3 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 
-							return this.requestService.request({ url: update.url, callSite: 'updateService.win32.downloadUpdate' }, CancellationToken.None)
+							return this.requestService.request({ url: update.url, callSite: NO_FETCH_TELEMETRY }, CancellationToken.None)
 								.then(context => {
@@ -304,3 +326,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);
@@ -368,20 +389,31 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun
 		await pfs.Promises.writeFile(this.availableUpdate.updateFilePath, 'flag');
-		const child = spawn(this.availableUpdate.packagePath,
-			[
-				'/verysilent',
-				'/log',
-				`/update="${this.availableUpdate.updateFilePath}"`,
-				`/progress="${progressFilePath}"`,
-				`/sessionend="${sessionEndFlagPath}"`,
-				`/cancel="${cancelFilePath}"`,
-				'/nocloseapplications',
-				'/mergetasks=runcode,!desktopicon,!quicklaunchicon'
-			],
-			{
+
+		let child: ChildProcess
+
+		const type = getUpdateType();
+		if (type == UpdateType.WindowsInstaller) {
+			child = spawn('msiexec.exe', ['/i', this.availableUpdate.packagePath], {
 				detached: true,
-				stdio: ['ignore', 'ignore', 'ignore'],
-				windowsVerbatimArguments: true,
-				env: { ...process.env, __COMPAT_LAYER: 'RunAsInvoker' }
-			}
-		);
+				stdio: ['ignore', 'ignore', 'ignore']
+			});
+		} else {
+			child = spawn(this.availableUpdate.packagePath,
+				[
+					'/verysilent',
+					'/log',
+					`/update="${this.availableUpdate.updateFilePath}"`,
+					`/progress="${progressFilePath}"`,
+					`/sessionend="${sessionEndFlagPath}"`,
+					`/cancel="${cancelFilePath}"`,
+					'/nocloseapplications',
+					'/mergetasks=runcode,!desktopicon,!quicklaunchicon'
+				],
+				{
+					detached: true,
+					stdio: ['ignore', 'ignore', 'ignore'],
+					windowsVerbatimArguments: true,
+					env: { ...process.env, __COMPAT_LAYER: 'RunAsInvoker' }
+				}
+			);
+		}
 
