Bureaucratic API design...

Bureaucratic API design...

Our software is used in 90 countries (last time I looked). Of course, being somewhat overly pedantic and in wish of control, I built our webshop. In Javascript. Then in Elm. Then in Javascript again. Oh, well.

Anyway, regarding the VAT. EU, in an effort to get a piece of the huge sales EU citizens are making with international mega-corporations, imposed a rule that VAT is to be paid to a country whose citizen (or company) paid instead of to a country where seller is incorporated. So, Double Irish with a Dutch Sandwich is finally no longer a problem. For states. But. Everyone single seller selling to EU nationals has a life massively complicated. Instead of a simple VAT charge to own country, we now have to charge VAT of the customer's country. VAT rates are different in every country and many countries have several VAT rates, depending on type of the goods sold. And, we have to pay each country VAT we collected. For a UK seller, it's trivial - HMRC allows us to send a specification and pay them a total, then they pay each country. Brexit is coming and nobody know what will be happening with VATMOSS in a few weeks. But I digress.

I'll focus on just a single part of the shopping experience here - VAT reversal to a business incorporated in EU. We need to charge any EU business a VAT unless they are VAT-registered and have a valid VAT number. To make sure they have a valid VAT number, we can do a syntax check via regular expressions. But this only means that the format of the number is valid - it doesn't guarantee that the number user typed has anything to do with any EU business, no to mention that it's the business specified in the order. And yes, seller is the one responsible if they do not charge a VAT when they should. So, let's see how can we check the VAT number.

European Commission has a nice little VIES VAT number validation form on their site where we can lookup a company from its VAT number.

Not really sure why do they need a requester info as well, but ignoring that seems to work. All right, so let's give it a try!

Eventually (and there are a few errors I don't mention here), a database lookup returns the info we need.

An interesting error message that pops up from time to time is that there are too many concurrent requests for the country in question. So, they don't rate-limit per IP, they rate limit per country. This makes as much sense as the rest of the architecture.

API to get this info programatically is ancient XML SOAP and not ubiquitous and simple JSON, to complicate things further.

However, the best part really is the architecture itself. It's designed like this: VIES API is only a proxy, forwarding requests to per-country servers. It adds additional time due to network lag, which should usually be a problem. It's not - for France, response time can get as high as 15 seconds... What is an additional delay of half a second in this light?

Now, regarding the maximum concurrent request limit I mentioned earlier... Seems that the fighting against it is solved by simply having ridiculously low limits, like a few hundred requests:

Why isn't the system designed so that each country updates the main EU database in real-time as companies are registered or dissolved, I really can't tell. Those are events that happen pretty rarely, I'd say in order of a few thousand per country per day. Even batching those changes and updating a central EU database once a day is a far better idea than what we have now. It's not rare that a country servers are down, so you can't check a VAT number.

With half a billion people in EU we need a high-resilience and low-latency API for a thing so commonly needed as a VAT number check. As it is now, web shops can resolve to only checking that number format is correct and skip the proper check, or they can rely on a terribly slow and unreliable API as a part of their core checkout flow - and risk a non-insignificant percentage of orders to fail.

The optimal way to approach this issue with a current terrible API would be to decouple order initialization and creation, so that VAT number is checked for syntax only, and the order is finalized when VAT is properly checked. This poses additional complexity, as background jobs should retry pinging the API until it succeeds or it's time to give up. It will often result in order being delayed. Additional costs, in the end, are simply thrown at the businesses implementing the web shops.

The optimal way to fix this issue is for EU to find funds to form a capable API team that does things right and forces EU countries to conform to the modern workflows. If we don't live to see that, our grandchildren might.