How to Handle VIES Downtime in Your Application
30 Mar 2026

VIES national nodes go offline. It is not an edge case – it happens regularly, especially for Germany, which is both the most important EU market and one of the most unreliable VIES nodes. Here is how to build a system that handles it correctly.
Why VIES goes down and how often
VIES is not a single system – it is a network of national nodes, each operated by a member state’s tax authority: the EU-27 plus XI for Northern Ireland, 28 codes in total. When you query VIES for an Irish VAT number, the European Commission infrastructure routes the request to Ireland’s Revenue Commissioners system in real time. If that system is unavailable, VIES returns an error.
Individual nodes go offline for planned maintenance, for unplanned outages, and for rate limiting – VIES has both a per-state and a global concurrency limit, returned as MS_MAX_CONCURRENT_REQ and GLOBAL_MAX_CONCURRENT_REQ. Outages last minutes or hours, and they are not evenly distributed: a handful of member states account for nearly all of the downtime, and Germany’s is a window at the same time every night.
The Commission publishes current per-country availability at ec.europa.eu/taxation_customs/vies/rest-api/check-status, but keeps no history behind it. We sample that endpoint every 15 minutes and keep every sample – the rolling per-country result, including which hours are worst for which state, is at vatnode.dev/vies-status. We also wrote up 30 days of those samples across all 28 member states, which is where the claim that the downtime is concentrated and Germany’s is scheduled actually comes from.
The VIES_UNAVAILABLE error
When the vatnode API cannot reach VIES for a given country, it returns HTTP 503 with a structured error body:
{
"error": {
"code": "VIES_UNAVAILABLE",
"message": "The VIES service for IE is temporarily unavailable. Retry later."
}
}
This is distinct from an invalid VAT number (HTTP 200 with "valid": false) or a format error (HTTP 400 with INVALID_FORMAT). A 503 always means ‘try again later’ – not ‘this VAT number is invalid’.
The right pattern: queue, not block
The most common mistake is blocking a checkout or invoice on VIES unavailability. This is wrong for two reasons:
- The customer is almost certainly legitimate. VIES being down does not mean the VAT number is invalid. The customer provided it in good faith and their registration is almost certainly still active.
- You cannot verify either way. Blocking is not a safety measure – it is just friction that loses you a sale.
The correct approach: allow the transaction to proceed, apply standard VAT (the safe default), and queue an async job to re-validate when VIES recovers.
async function validateVatForCheckout(vatId: string, customerId: string) {
const res = await fetch(`https://api.vatnode.dev/v1/vat/${encodeURIComponent(vatId)}`, {
headers: { Authorization: `Bearer ${process.env.VATNODE_API_KEY}` },
})
if (res.status === 503) {
// VIES unavailable — queue for retry, do not block
await queue.add('validate-vat-retry', {
vatId,
customerId,
scheduledFor: Date.now() + 5 * 60 * 1000, // retry in 5 minutes
})
return {
valid: null, // unknown — pending retry
vatRate: 0.2, // apply standard VAT in the meantime
requiresRetry: true,
}
}
const data = await res.json()
return {
valid: data.valid,
vatRate: data.valid ? 0 : 0.2,
checkId: data.checkId,
requiresRetry: false,
}
}
Germany has no fallback
Germany is the member state you would most want a fallback for, and it is the one member state where none is available.
The German Bundeszentralamt für Steuern operates its own VAT validation service, eVatR, which looks like the answer. It is not: eVatR only answers a German business asking about a foreign VAT number. Confirming a German number through it requires an entitlement we do not hold – every request we made came back evatr-0006, not authorised.
So when the VIES DE node is down, a German number returns VIES_UNAVAILABLE and there is nothing behind it. You wait, or you queue. Since the DE outage window is predictable, queueing is usually enough: work scheduled inside it will succeed on the next attempt after it closes.
Which countries do have a working fallback is a narrower list than it looks, and the reason is that a national VAT register and a national company register answer different questions. Poland’s MF, Romania’s ANAF and the Czech ARES DPH status expose the VAT register itself, so they can answer the validity question. Company registers – Finland’s PRH, France’s SIRENE, Denmark’s CVR, Sweden’s Bolagsverket, the Belgian CBE – cannot: a company can be listed and active there without being VAT-registered at all. We use those to enrich a result, never to decide one. The Netherlands has no register behind it either way: NL is VIES-only, so a Dutch check returns the VIES name and address and nothing more.
Retry strategy
When VIES is unavailable, a good retry strategy uses exponential backoff with a maximum delay. Size the delays in minutes, not seconds: the outages we have measured run from a few minutes to several hours, so a schedule that exhausts itself inside the first minute reports a hard failure while the node is merely busy.
// Retry intervals (minutes): 5, 15, 30, 60, 120
// After 5 retries (~3.5 hours), flag for manual review
const RETRY_DELAYS = [5, 15, 30, 60, 120]
async function scheduleVatRetry(vatId: string, customerId: string, attempt = 0) {
if (attempt >= RETRY_DELAYS.length) {
// Flag for manual review after exhausting retries
await flagForManualReview({ vatId, customerId })
return
}
const delayMs = RETRY_DELAYS[attempt] * 60 * 1000
await queue.add(
'validate-vat-retry',
{ vatId, customerId, attempt: attempt + 1 },
{ delay: delayMs }
)
}
If you are considering moving away from a direct SOAP connection to VIES, the VIES REST API alternative with automatic fallback covers the migration path and what changes in your codebase.
Build a resilient VAT integration with vatnode
vatnode handles retries, national-registry fallback where available, and structured error codes so your application can implement the right pattern. Free plan, 100 requests/month.