The problem with waiting

Enterprise workstations are notoriously slow to update software. IT departments operate on maintenance windows, change control processes, and risk-averse policies that are there for good reason. But browser extensions distributed through the Chrome Web Store or Edge Add-ons store introduce a different kind of lag — one that's entirely outside your control. You submit an update, and then you wait. And wait. And wait some more while the store's review process runs its course and Chrome's auto-update mechanism eventually decides to pull the new version down to each machine.

For CoApp, that lag is not an abstract inconvenience. Our extension sits inside live clinical and operational workflows. When we ship a security fix, a bug patch, or a new detection rule, we need every workstation running that update as fast as possible — not within 48 to 72 hours after the store review clears, not whenever Chrome decides to check for updates on its own schedule. We need it now, on our terms.

This post explains how we built a self-hosted update system that gives CoApp complete control over when and how enterprise workstations receive extension updates.

The web store dependency problem

Both the Chrome Web Store and Edge Add-ons store add non-deterministic latency to your deployment pipeline. The review process for Chrome extensions typically runs between several hours and a few days. Edge's review times are similarly variable. Once an update clears review and goes live on the store, you still have no control over when Chrome pulls the update down to individual machines.

Chrome's built-in extension update check runs on an interval — roughly every 5 hours for most installations, though the exact timing varies. Enterprise group policy can influence this somewhat, but you cannot reliably force an immediate update through Chrome's native mechanism alone when extensions are distributed through the store. You're at the mercy of the store's review queue and Chrome's update scheduler.

Every machine running an outdated version of a security-critical extension is a compliance liability. For CoApp customers running operations across multiple locations, that's not a theoretical risk — it's a concrete gap in their operational control posture.

The solution is to remove the web store from the loop entirely. Self-host the extension, self-host the update manifest, and use Chrome's enterprise policy infrastructure to point all workstations at your infrastructure instead of the store.

Self-hosting the extension

Chrome's enterprise extension infrastructure supports a concept called a "force-installed extension from an update URL." Instead of force-installing from the web store, you configure group policy to point Chrome at a URL you control. The URL points to an update XML manifest file — a small document that tells Chrome what version is current and where to download the extension package.

To make this work you need three things: a stable app ID (the extension's unique identifier), a hosted .crx file, and a hosted update XML manifest. The app ID is set once in your group policy configuration. It must match the ID embedded in the extension's .crx package — the ID is derived from the private key used to sign the extension, so keep that key safe.

CoApp hosts both the .crx file and the update manifest on S3, fronted by CloudFront. This gives us low-latency delivery to enterprise workstations across the country, high availability, and zero operational overhead on our end. A CloudFront distribution is purpose-built for exactly this kind of static file delivery at scale.

The group policy configuration is pushed once by the customer's IT team. After that, every workstation that receives the policy will automatically pull CoApp's extension from our servers and keep it current — no store involved, no review queue, no waiting.

The update XML manifest

The update manifest is a small XML file that Chrome fetches when it checks for extension updates. Its structure is straightforward:

<?xml version="1.0" encoding="UTF-8"?>
<gupdate xmlns="http://www.google.com/update2/response"
         protocol="2.0">
  <app appid="YOUR_EXTENSION_ID_HERE">
    <updatecheck
      codebase="https://cdn.example.com/ext/coapp-1.4.2.crx"
      version="1.4.2" />
  </app>
</gupdate>

When Chrome checks for updates, it fetches this manifest from the URL configured in group policy, reads the version attribute, and compares it against the currently installed version. If the manifest version is higher, Chrome downloads the .crx from the codebase URL and installs it. If the versions match, Chrome does nothing and waits for the next update check cycle.

Deploying an update is as simple as uploading a new .crx to S3 and updating the manifest's version and codebase fields to point to it. We then issue a CloudFront invalidation on the manifest file so all edge nodes serve the new version immediately — no stale cache serving the old manifest while the new .crx is live.

In-extension update logic

Chrome's built-in update check runs on its own schedule, which is sufficient for most deployments. But for time-sensitive updates — security patches, critical bug fixes — we wanted a faster path. CoApp's extension includes its own update check routine that supplements Chrome's native mechanism.

On a configurable interval, the extension fetches the update manifest from our CDN and parses the current version. If the manifest version is higher than the running version, the extension calls chrome.runtime.requestUpdateCheck() to prompt Chrome to check for and apply the update. It then listens for chrome.runtime.onUpdateAvailable, and when that event fires, calls chrome.runtime.reload() to apply the update immediately without waiting for a browser restart.

This gives CoApp a fast-path update mechanism: publish the new .crx, update the manifest, and within one check interval every running instance of the extension self-updates — no IT intervention required, no waiting for Chrome's native update cycle.

Handling failure and throttling

Chrome throttles calls to chrome.runtime.requestUpdateCheck(). If you call it too frequently, Chrome returns a throttled status rather than checking for updates. CoApp's extension handles this gracefully: if a throttled response comes back, it logs the event, backs off exponentially, and retries after a delay. The check interval itself is tuned to stay comfortably within Chrome's rate limits under normal operation.

Network failures during manifest fetch are handled with a simple retry with backoff. If the manifest can't be reached after several attempts, the extension logs the failure and continues running on its current version. Deployment state — what version each workstation is running, when it last successfully checked for updates — is surfaced through CoApp's operations dashboard, giving IT teams visibility into extension coverage across the fleet without manual auditing.

Why this matters beyond convenience

It's tempting to frame self-hosted extension delivery as a developer convenience story — control over your release schedule, faster iteration cycles, simpler deployment. Those benefits are real, but they're secondary. The primary reason CoApp built this infrastructure is security and compliance.

A browser extension that processes operational data inside live clinical workflows is part of your security posture. Every workstation running an outdated version — one that might lack a security patch, a data validation fix, or a corrected detection rule — is a workstation where your operational controls are degraded. In a multi-location business with dozens or hundreds of workstations, the probability of at least one machine being significantly behind is high when you're relying on store distribution and browser auto-update.

Self-hosted distribution with in-extension update logic closes that gap. When CoApp ships a security-relevant update, it lands across the entire customer fleet within hours, not days. That's not just better software delivery — it's a compliance capability that multi-location operators can speak to directly when they need to demonstrate operational control.