How often is VIES actually down?
Everyone building EU VAT validation eventually learns that VIES is unreliable. What nobody publishes is how unreliable, per country, with numbers you can check.
Figures do circulate. We have seen “32% monthly downtime” quoted for Germany and Belgium in competitor marketing, with no methodology attached. So we started measuring instead, and this page is the result.
228,956 measurements. 27 member states and Northern Ireland — 28 registries — over the last 30
days, 8,177 samples each, as read on 22 October 2026. The live version of this data is at verifnow.io/en/status , and the raw
feed is public at GET /api/v1/status/vies — no API key.
The numbers
| Member state | Available | Roughly, unreachable over 30 days |
|---|---|---|
| 🇩🇪 Germany | 81.23% | ~135 hours |
🇬🇷 Greece (EL) | 90.20% | ~71 hours |
| 🇱🇻 Latvia | 91.48% | ~61 hours |
| 🇭🇺 Hungary | 98.18% | ~13 hours |
| 🇨🇿 Czechia | 98.52% | ~11 hours |
| 🇱🇹 Lithuania | 98.89% | ~8 hours |
| 🇮🇹 Italy | 99.12% | ~6 hours |
| 🇫🇮 Finland | 99.13% | ~6 hours |
| 🇮🇪 Ireland | 99.16% | ~6 hours |
| 🇲🇹 Malta | 99.43% | |
| 🇩🇰 Denmark | 99.56% | |
| 🇪🇪 Estonia | 99.61% | |
| 🇳🇱 Netherlands | 99.73% | |
Northern Ireland (XI) | 99.83% | |
| 🇷🇴 Romania | 99.87% | |
| 🇫🇷 France | 99.89% | |
| 🇧🇬 Bulgaria · 🇱🇺 Luxembourg · 🇵🇹 Portugal · 🇪🇸 Spain · 🇧🇪 Belgium · 🇭🇷 Croatia | 99.90–99.98% | |
| 🇦🇹 Austria · 🇨🇾 Cyprus · 🇵🇱 Poland · 🇸🇪 Sweden · 🇸🇮 Slovenia · 🇸🇰 Slovakia | 100.00% | none observed |
The median registry sat at 99.85%. That is the part most people get wrong: VIES is not uniformly broken. Twenty-two of twenty-eight registries were above 99%, and six showed no failure at all.
The problem is the tail. Three registries fell below 95%, and Germany spent roughly 135 hours — more than five days — unreachable. If your customers are German, Greek or Latvian, “VIES is usually fine” is not a useful statement.
The ranking moves, and the tail does not. The first version of this page covered the nine days to 14 September: Latvia was at 76.33%, Germany at 84.12%, Belgium at 85.89% and Cyprus at 89.86%. Over the 30 days to 22 October, Belgium is at 99.98% and Cyprus at 100.00%, while Germany, Greece and Latvia — all three already below 95% in the first version — are still at the bottom. The two windows do not overlap, so neither is wrong: a registry can have a bad week, and a short window flatters or punishes it.
What we actually measured
Being precise about this matters, because the number means different things depending on how it was produced.
We did not probe each registry ourselves. The European Commission publishes its own per-country availability feed. We read that feed every five minutes and keep the history — which the Commission does not, since its feed reports only the current moment.
We skip a reading rather than record a false one. If the Commission’s feed itself cannot be reached, nothing is stored that round, so our own network trouble is never charged to a registry. That, and the five-minute wait after each reading, is why every registry has 8,177 samples in 30 days instead of the 8,640 a strict five-minute clock would give: one reading every 5 minutes 17 seconds on average.
We do correct it downward. When our own lookups to a country fail three times in a row, we record that country as unavailable for as long as our circuit breaker stays open, regardless of what the feed claims. A registry that reports itself healthy while refusing requests is counted as down.
So the figures are the Commission’s own self-assessment, made durable and made stricter. They are not an independent probe, and we would rather say so than imply a rigour the method does not have.
It also means these figures are not directly comparable to the 32% quoted at the top of this page. We don’t know how that number was produced, and our method reads the Commission’s own feed, which may understate the request failures a caller actually experiences. The point is not that one number is right and the other wrong — it is that only one of them tells you how it was measured.
Thirty days is a better window than nine, and still a short one: a single long outage still moves a registry’s figure a lot. Treat the ranking as informative and the precise decimals as provisional. The status page always shows the current thirty-day window.
Why this breaks checkouts
A VAT lookup that fails is not the problem. The problem is what most code does next.
VIES answers HTTP 200 during an outage, carrying the real outcome in a userError field. Code that only checks the status code reads an outage as a successful not registered answer — and rejects a legitimate customer at checkout.
That failure is not evenly distributed either. Two of the codes VIES returns are rate limits, which means the failure arrives precisely when your traffic is highest.
// What an outage looks like. Note the status code.
HTTP/1.1 200 OK
{ "isValid": false, "userError": "MS_UNAVAILABLE" }Reading isValid here tells your customer their VAT number is not registered. It is.
What to do instead
Treat “registered” as three states, not two. A lookup can say yes, say no, or fail to say anything — and the third is not the second.
import { VerifNow } from '@verifnow/sdk'
const client = new VerifNow({ apiKey: process.env.VERIFNOW_API_KEY! })
const { vatDetails } = await client.validateVat(vatNumber)
if (!vatDetails!.formatValid) {
// Structural, decided locally, never depends on VIES. Safe to reject.
return reject('That VAT number is not correctly formed.')
}
if (vatDetails!.registered === false) {
return reject('That VAT number is not registered.')
}
if (vatDetails!.registered === null) {
// The registry was down. Accept, flag it, re-check later — do not reject.
await queueForRecheck(vatNumber)
return accept({ verified: false })
}
return accept({ verified: true, stale: vatDetails!.source === 'STALE' })registered is null — never false — when the registry could not be reached, and source tells you where the verdict came from:
source | Meaning |
|---|---|
LIVE | Confirmed against VIES during this request |
CACHE | A VIES answer less than 24 hours old |
STALE | VIES was unreachable, so an older answer was used |
UNVERIFIED | VIES was unreachable and nothing was cached |
During Germany’s roughly 135 hours in these 30 days, a caller gets STALE with a real verdict if we have seen that number before, and UNVERIFIED if we have not. Neither is a rejection.
You can implement all of this against VIES directly — the contract matters more than the vendor. If you would rather not, VerifNow does it behind one endpoint, and the free tier covers 250 validations a month.
Check it yourself
The feed behind this page is public and takes no API key:
curl https://api.verifnow.io/api/v1/status/vies{
"generatedAt": "2026-10-22T01:08:22Z",
"windowDays": 30,
"viesReachable": true,
"lastCheckedAt": "2026-10-22T01:05:39Z",
"countriesTracked": 28,
"countriesUnavailableNow": 0,
"countries": [
{ "countryCode": "DE", "availableNow": true, "availabilityPercent": 81.23, "sampleCount": 8177 }
]
}If you are building anything that depends on VIES, monitoring it is cheap and the alternative is finding out from support tickets.
Related
- Validate VAT — the full degradation contract
- Validate IBAN — the other field a billing form depends on
- Node.js examples —
@verifnow/sdk