Making backend API services easy to use and work with!
What makes a backend service (that exposes functionality in the form of ReSTful APIs) fun to work with? Not just for the devs working on the service but also for everyone else using it including but not limited to developers who consume those APIs. I think this question is more valuable if flipped: What makes working with a backend service a nightmare? What feels like you are fighting the service at every point in your code?
In this post I want to draw on my experience building API services and talk through a few considerations I like to look into while building backend services. Some of these could be provided by the framework itself while others might be functionality worth building!
Consistent API naming that includes everything API related: paths, requests, responses and headers! This allows working with APIs more easy and it set a nice consistent pattern for all new APIs. Teams the consume this API will see a more predictable pattern that makes consuming the APIs easy.
Consistent Error Structures
I dedicated a whole section to error responses because this is probably one area, I wish more APIs prioritized consistency for! It is hard to work with services that don’t pass back a consistent error response for all APIs. It is possible to have certain fields in the error response be absent or present depending on the particular error but having the same over all structure makes working with these APIs very easy because consumers of the API can dedicate a central location to handling errors vs having to handle API specific errors. Similarly devs building these services can create and use error handling at a global level vs having different error responses come from different sections of the backend service.
Logging is the core of any software application. Backend services are no different! It is important to identify all the places that require logging and pick the right log level so that it makes logs reading easy in tools like Splunk (easier to filter all the error level logs vs the debug logs etc). Along those lines it is more important to make sure the things that are logged DO NOT contain sensitive information of any kind. This includes (but is not limited to) Personally Identifiable Information aka PII, API keys, authentication credentials etc. It is extremely important to make sure these values are not logged in plain text because that is a trap that is easy to fall into and could bear unwelcome consequences.
When something goes wrong, more often that not, it helps to know the entire journey of a request: Where it came from, what came in, what time was the request received, what the backend service did to handle that request, what other API services (if any) were called etc. The ability to trace a request all the from what was received to what was sent back helps in keeping track of request handling and debugging.
Support for Secrets
There is going to be atleast one secret that your application is going to need, unless you are building a “Hello World” application. When I say secrets, I mean everything that is sensitive that should not be exposed to the whole world, anything you would never check into source control. API keys, secret values to access other services/applications, signing keys, expiration times, username/password credentials etc. When building a backend service it is important to make sure that the app or the app and the host provider (if your app is going to be deployed to the internet) have some kind of support for secrets. This includes being able to host and store secrets in such a way that only authorized personnel can manage those secrets. Some platforms take this a step further and also provide the ability to rotate secrets on a regular basis. This is very powerful because this your backend service a little away from being the weakest link in the chain. Noteworthy while we are on the topic of secrets is, to never (ever) commit your secrets to source control. If that happens there are tools to revert those commits and remove it from source control but in some cases it might be easier to just re generate that secret, invalidating the old one.
Support for API documentation
Documentation is the bridging language between everyone who consumes a backend service and the rest of the world. While picking a framework to build your service or as you are building your service it is important to think about how all the APIs are going to be documented. This should be usable by any team that wants to consume your APIs. Swagger hub is a very popular and widely used tool. Other options include Spring Rest Docs, if you are building your service on a Spring stack. If the generation of documentation is closely coupled to the code itself, meaning any new updates to the code will automatically update the documentation, that would be an added bonus because it relieves developers from having to constantly keep the code and documentation on par.
Software solutions are build for people, by people. Making sure your application is easy and friendly to use, not just for the end users, but also fellow teammates goes a long way in ensuring a solid product that can be iterated over successfully if the right patterns are put in place starting as early as possible.