APIs. You depend on them, but can you always trust them to work as advertised? The truth is that APIs can fail, and even when they don't fail, they can perform in ways that are less than adequate. When that happens, your application may be left hanging, or worse yet, it may crash. What kind of failures are we talking about, and what can you do about them?
First, though, consider what an API does—It provides a way for a programmer to communicate with an external application or service, and to ask that application to do something. You may or may not know what the other program does internally with your data and your request, but as long as everything works correctly, all you need to know is how to use the API. But that is not enough to ensure that APIs perform adequately.
In this article, we'll look at three common reasons why an API might fail or underperform, and how DevOps engineers can address them.
1. Things Change Quickly
Software changes may take a while to show up in the documentation. And an API call that worked in the last version of the other program may no longer work in the current version. It may now require different syntax, new arguments, or new formatting for existing arguments, or it may output data in an unexpected form.
Backwards Compatibility — Or Not?
Ideally, of course, API developers will maintain backwards compatibility, so that old API calls continue to work, and they will have updated the API documentation to reflect the changes. But for a variety of reasons, backwards compatibility may not always be feasible, or may be available only for a limited grace period. Once the grace period is over, non-updated API calls will no longer work.
If you're adding an API to your code and are working from the latest documentation, new changes may not give you any problems, because you'll take them into account when you incorporate the API into your application. But if the API calls have been in your code for some time, you may not be aware of the changes until they suddenly fail. When that happens, you may not even realize that the problem is with the API (which had, after all, been working) until you track it down to its source.
Go to the Source
The documentation that you're working from may not be up-to-date. If you get it directly from the developers' site, chances are good (although not perfect) that it will be current, but it's all too easy (particularly with open-source software) to find yourself using outdated documentation, whether you found it sitting in a convenient directory on your local network, or at a third-party site that popped up in a search engine. When in doubt (or even when not in doubt), go to the source.
Dependencies Can Change
Note that the above also applies to dependencies and support applications and services which the other API may use. If you haven't been keeping track of all of the changes to the other program, its developers may have been doing the same thing — your API call may fail because one of their API calls wasn't updated. It's not fair, but it can happen, and when it does, tracking the root problem down may take some detective work on your part.
2. Communication Breakdown
Let's talk about communication. Chances are more than good that the program or service that you're trying to connect with is somewhere online (as opposed to running on the same desktop computer or LAN as your application, which would probably have been the case a generation or so ago). It may be an instance of an application running on a cloud-based server, or it may be a service built into a cloud platform infrastructure. Its location (from the point of view of your code) may be a URL, or some even more abstract proxy address.
Seamless Redirection Isn't a Given
What happens if the connection to that address doesn't work — if the hosting service fails, or is overloaded with requests, or if there is a failure in the communication infrastructure? In some cases, your call may be redirected gracefully (i.e., in a way that requires no added response at your end) to an alternative address. In other cases, however, you may receive a 3xx response code (requiring action on your part), a 4xx or 5xx error code, or worse, no response at all.
Don't Hang Up
A hanging application is as bad as (and often worse than) a crash. If your application depends on a response from an external program or service, you need to include ways of dealing with timeouts and failed connections, and you need to be able to recognize and respond correctly to redirection and error codes. If your application cannot continue to function without a response to the API call, it should fail gracefully, saving user-entered data to temporary storage.
3. Bad Data Is No Excuse
Your API call is probably one connection in a series, taking data from upstream, moving it downstream, then passing the response on, either back upstream or in a new direction. You may not know where that data originated, or everything that's happened to it. What happens if it is not in the format that the API requires, or that the other program expects? What happens if it includes unacceptable characters (system-reserved, unexpected double-byte text, etc.)?
Validate, Check, and Filter
if you're lucky, you'll get an error code or some other kind of reasonably informative response from the other program; if you do, you need to be able to recognize it and respond appropriately. If you're not so lucky, the other program may not respond, or it may pass bad data further downstream, or back to your application. This is (among many other reasons) why it's important to validate data, check for type and formatting problems, and filter out anything that shouldn't be there.
More Than Enough API Pitfalls
There are plenty of other things that can cause API failure: slow connections or servers, problems with security certificates or other credentials, limits imposed by the API service vendor (traffic volume, subscription expiration, service area), or DDoS attacks that take down a large chunk of infrastructure, to name just a few.
Conclusion: It Is Your Responsibility
The bottom line is that when an API fails, that's not what users are going to see. What they will see is your program failing, and they'll hold you responsible for the failure. You need to anticipate and prepare for API failures just as you would for any other kind of bug or failure. How can you do this?
- Check for timeouts. Don't let any non-responsive API hang your application. If your program needs data from the API in order to continue, let users know that the remote service isn't responding, and give them the option to increase the wait period or try again later.
- Validate, format, filter, and otherwise clean up outgoing and incoming data. Know what the API requires, and know what the code on your side requires from the API. Keep it clean.
- Test your system's response to API failures. Add virtual APIs to your test regime. They should simulate both successful responses and all of the failure conditions that you can anticipate.
- Put yourself in your users' shoes. Know what API failures for key services look like from their end, and make the process as painless as possible for them.
You may not be able to prevent APIs from failing, but you can contain the damage, and prevent a failed API from bringing down your application as well.