While not exactly for Xamarin Forms, as a Xamarin Forms developer you are highly likely to be working against an API. Sometimes this is already existing or you are implementing against a 3rd party. But in the times you get to design one yourself, even if its not going to initially be a global highly used API, this is how you start off on the right foot. You can say this blog post is more for startups rather than enterprise. I will also use Azure as an example here but their are similar technologies with other cloud providers e.g. AWS.
Why would you chose to split up an API, all dealing with one system into many APIs? The answer is to reduce complexity and dependencies. Have you ever started out a project, thought it was great, clean and easy to maintain, then about 2 months later you are looking at it going, how did this go all wrong, why are they dependencies infecting every area? This normally happens most frequently with something like a user table or object that seems to be connected to every part of the system.
What is needed is an API per aspect of the system. For example Users, Inventory, Locations should all be set to different API’s as they all deal with different aspects of the system, however they are related.
Create a separate REST API for each of these systems with defined inputs and outputs. You can use something like RAML to create the definition. The great benefit of this is you can define an API contract, give it to a developer and let them complete it. Lets say that the inventory database becomes so large and inefficient that it needs a NoSQL solution, you can keep the API the same and wipe out all code beneath it and replace it. All other systems keep working and don’t even know that another API just changed its entire code base, or data storage solution.
These API’s will be stateless and require basic authentication but generally aren’t publicly accessible. The reason is we still need to verify that a User can add a location or inventory can be added to a location.
This is where a gateway API comes into play. Companies such as Netflix and Amazon use this approach to provide a single accessible API for their client software to connect to but then redirect to the appropriate system. This is also where the gateway can do cross dependency checks. If you want to add a location but need to check if they can do that, do it at the gateway level.
A database or at least different schema in the same database is needed to support the design of micro services. Lets look at an imaginary example in that most applications have user tables.
You will notice each is separated, yet the data in one database references that of another database, such as inventory.Location references the inventory ItemId and the LocationId. So how do you ensure referential integrity across these separate databases.
Here is the thing, you don’t. In all of my years as programming, when did I ever come an error in a production system where I went, thank goodness we had referential integrity otherwise we would have put a bad id in that column? The answer is never. In order to enjoy the fact your API projects won’t clutter up each other, they need to be kept completely separated.
Use a Guid as your PK on all tables. Now before you all go and grab your torch and pitchforks and chase me down the street because we all know you don’t want a clustered index as a Guid, it provides terrible write performance. We have a simple solution. Don’t use your primary key as a clustered index. Create another column
ALTER TABLE user.User ADD ClusteredIndex bigint identity(1,1)
CREATE CLUSTERED INDEX ci ON user.User(ClusteredIndex)
Note: With Azure you need to stop the default clustered index attached to the primary key from being created. SQL Azure can’t insert any data into the table until a clustered index is set, but you can create a table without a clustered index first, before adding one to it.
Azure SQL Data Sync will allow you to keep a database in sync within a 5 minute window between two or more databases in separate server or even data centers. You will be able to
The only thing you need to remember here is to not sync our clustered index. Manually untick the ClusteredIndex columns to ensure they aren’t replicated as there is no point at all, they are only for the local SQL Azure cluster.
With the above in place, a stateless API, with a database that is synchronized where it is needed, you are now able to easily implement load balancing and automatic fail overs.
Load balancing is fairly simple for web or API apps and now also includes sticky sessions which really helps if your API or web app is caching data locally. You can configure load balancing in the portal, give it parameters of when to scale up (e.g. CPU at 80% usage) and the maximum you will scale it up to. The load balancer will automatically distribute the load across the instances.
Data Center Fail Over
Moving traffic to a closer endpoint to the client and having a failover to another data center (trust me its needed, I had everything in one data center in the earlier years of Azure, naively believing data centers don’t go down). This is all quite easily accomplished by the Azure Traffic Manager.
Setup an API in another data center. Setup the database in the same data center so that they can both run together by themselves. Setup the Azure SQL Data Sync and Traffic Manager appropriately and then if a data center does go down everything will re-route to the other data center.
You may lose 5 minutes worth of data that will be restored once the new data center comes up again and experience 5 – 15 minutes of downtime for some users. But if that is all you have to deal with from a complete data center failure, your API infrastructure is in good shape. You could even sleep through this one.