How this is calculated
Every number on this site comes from a public release record you can check yourself. This page gives you the whole formula, the sources, and the parts we know are imperfect.
What this measures, and what it does not
This index measures maintenance: whether a vendor is still shipping software to the people paying for it. Unmaintained VPN clients stop getting protocol fixes, operating-system compatibility patches, and responses to disclosed vulnerabilities, while the subscription keeps billing. That is a real and checkable risk, and almost nobody tracks it.
It is not a quality score. It says nothing about speed, server count, logging policy, jurisdiction, audit history, or whether a provider deserves your trust. A VPN can ship every week and still be a bad VPN. Use this to rule things out, then read a real review.
The formula
For each platform a vendor ships, we compute two things.
Recency — how long since the last release, decaying on a 45-day half-life.
recency = 0.5 ^ (days_since_release / 45) A release today scores 1.0. 45 days ago, 0.5. 90 days ago, 0.25. A year ago, effectively zero.
Cadence — how many releases in the past year, capped at 12.
cadence = min(1, releases_in_365_days / 12) Shipping 12 times a year earns full marks. Shipping 60 times earns exactly the same — volume past monthly is not evidence of better maintenance.
Platform score weights recency more heavily than cadence, because a vendor that shipped steadily and then stopped is the exact failure this site exists to catch.
platform = 0.6 × recency + 0.4 × cadence The index is the weighted average across the platforms a vendor actually ships, multiplied by a coverage factor.
index = 100 × weighted_average × coverage coverage = 0.75 + 0.25 × (platforms_shipped / all_platforms) Coverage never drops below 0.75, so a small provider that maintains three platforms well is not crushed by a large one that maintains eight indifferently. It still rewards breadth, because an abandoned Linux client is a real problem for the people using it.
Platform weights
| Platform | Weight |
|---|---|
| Windows | 1.0 |
| Android | 1.0 |
| iOS | 1.0 |
| macOS | 0.9 |
| Linux | 0.7 |
| Chrome | 0.5 |
| Firefox | 0.5 |
| CLI | 0.3 |
Rules that stop the score being gamed
- A version bump has to be real. If a store shows a new date but the same version number, it does not count as a release.
- Releases within 72 hours collapse into one. Pushing one build to four channels is one release, not four.
- Pre-release channels are excluded. Betas, alphas, release candidates and nightlies do not count. Shipping nightlies is not the same as shipping to users.
- Cadence is capped at 12 a year, so no amount of version churn buys a higher score.
- The same release from two sources counts once. Version
strings are normalised, so Windows Package Manager reporting
8.10.3.0and Chocolatey reporting8.10.3are recognised as one build.
Where the data comes from
| Source | Covers | Method | History |
|---|---|---|---|
| Apple App Store | iOS, macOS | iTunes Lookup API | Current version only |
| Google Play | Android | Store listing | Current version only; Play publishes no version string, so we key on the date |
| Chrome Web Store | Chrome | Store listing | Current version only |
| Mozilla Add-ons | Firefox | AMO public API | Full dated history |
| winget-pkgs | Windows | Microsoft manifest repo | Full dated history |
| Chocolatey | Windows | Community OData feed | Full dated history; volunteer-maintained, can lag |
| Homebrew Cask | macOS | homebrew-cask commit log | Full dated history; volunteer-maintained, can lag |
| GitHub Releases | Linux, CLI, apps built in the open | GitHub API | Full dated history |
How we check our own numbers
Being wrong about a real company is the failure mode that matters here, so the data is checked four ways, and the checks are part of the build rather than something we did once.
- Every source is re-fetched and compared against what we published, so a collector that quietly breaks or goes stale is caught.
- Where two sources cover one platform — Windows appears in both Microsoft's and Chocolatey's registries — we check they agree, and flag it when they do not.
- Impossible values are rejected: dates in the future, dates before app stores existed, versions that go backwards.
- Platforms that disagree by more than a year are flagged for review. This one matters most, and it is explained below.
Why "last release" can flatter a vendor
The date in the leaderboard is the vendor's freshest platform. A provider can ship a routine phone update while their desktop client and browser extension sit untouched for years, and that single date would make them look active.
So where a vendor's stalest platform trails its freshest by more than six months, the leaderboard says so directly — "oldest 3 years ago" beside the headline date. The index already accounts for this, because it averages across every platform a vendor ships rather than taking the best one; the warning exists so the table does not tell a rosier story than the score.
Known gaps
These are limitations we would rather state than have you discover.
- Google Play publishes no version number, only a date. A silent re-publish there can look like an update. Every other source gives us a version string to check.
- Microsoft Edge add-ons and Fire TV are not tracked. The Edge store is rendered in the browser and exposes no usable public endpoint; Amazon's app store has no public API at all.
- Chocolatey and Homebrew are community-maintained. Their timestamps can trail a vendor's actual release by a day or two. Where a first-party source exists, it wins.
- Not every vendor has every platform mapped. A platform we cannot confirm an identifier for is shown as untracked on the vendor's page, never counted as an abandoned platform.
- Closed-source desktop apps that auto-update silently may ship fixes that never appear in a package registry. Where that happens the index understates them.
- If a source breaks, we hold the previous value rather than letting a scraper failure look like an abandoned product. Those entries are marked on the vendor page, and if too many break at once the day's update is abandoned entirely rather than published wrong.
Independent audits
Audit records are curated by hand from vendors' own
publications. There is no API for this, and an audit is a claim about a
real company, so nothing here is inferred: every record links to a primary
source, and scripts/verify-audits.ts re-checks
each link on every build.
Audits are shown beside the index and never inside it. Folding them in would mean weighting a Cure53 app pentest against a Deloitte no-logs engagement, which are not the same thing and cannot be fairly traded off against each other in one number.
- "No audit on record" means we have not verified one — not that none exists. The dataset is deliberately incomplete rather than padded out with claims we could not check.
- Scope matters more than the badge. An application penetration test says nothing about whether a provider keeps logs, and a no-logs engagement says nothing about code quality. Every entry states which one it was.
- Some vendors block us. Where a site sits behind a bot filter we could not open the page to read which firm performed the audit. Those entries say "Not confirmed" for the auditor rather than guessing, and explain why on the vendor's page.
- An audit is a snapshot. It describes what an auditor saw on a particular date under an agreed scope. It is not a warranty, and it ages — which is why we show how old it is.
The attention chart
The attention page plots relative Google search interest. It is genuinely interesting and it is not part of the index, because search volume mostly tracks advertising spend. A ranking weighted by it would be a ranking of marketing budgets, which is the thing this site exists to be an alternative to.
Google Trends compares at most five terms at a time and rescales each query to 0-100 against that query's own peak. To place every brand on one axis we run batches of four brands plus a shared anchor brand and rescale each batch so the anchor matches. Two consequences worth stating:
- Small brands cannot be resolved. Against a large anchor they sit at the floor. We label those "below measurable threshold" instead of printing a zero, because low search volume is not zero search volume and says nothing about product quality.
- The most recent week is discarded. Trends' final bucket is a partial week and reads erratically, so we drop it rather than publish a cliff or a spike that is an artifact of timing.
Money
Some outbound links are affiliate links and we may earn a commission. The ranking code never reads the affiliate list — it is a separate file, loaded by the page renderer and not by the scorer. Every input to the index is public, so if a ranking ever looked bought, it could be checked and disproved. That is the point of publishing the formula.
Corrections
If a vendor is mapped to the wrong app, or ships a platform we are missing, that is a bug worth fixing. The whole release history is public data — send the identifier and we will add it.
Rebuilt daily at 5:00 PM Pacific.