I was recently fortunate enough to hear Nathan Totten‘s talk about the architecture of the Tankster game. What interested me was the broadly CQRS approach to the architecture of the game. As a means of comparison, a traditional web service provides CRUD operations via a RESTful interface like this:
Tankster on the other hand, has a Web Service for write only. This service essentially ends up placing JSON documents in Windows Azure Blob Storage. The documents are made publicly available, and are laid out in such a way that they look like a read only RESTful interface. Clever. Now your solution has a highly scalable read capability which you’re paying a very low cost for, you’re certainly not paying for the compute to deliver it (in Azure you pay for storage, transactions and egress on blob storage, and compute by the hour).
In the case of Tankster there is no security around the GETs on the Blob Store. The URLs are Guids which are hard to guess, and in any case, it’s only game state. Security could be added by creating shared access signatures for the blobs you wish to provide read access to.
But what would happen if you took this example a stage further? Why use your compute to to write to Blob Storage? All your code needs to do is decide which resources a client should be allowed read/write access to, the actual transfer of data to these endpoints is not something you need to be involved with (unless input validation is required). We could turn our application into a resource facilitator rather than a resource provider.
In fact, as of the June 2012 refresh, Shared Access Signatures can also be created for Queues and Tables. So direct access to these resources could also be provided.
How would this work if the client was a web browser? Well let’s assume it’s a single page application (now called an SPA apparently). The web page and associated scripts and resources are all static, so can be placed in Blob Storage. Calls to the REST Web Service included the identity of the user, and can be achieved using GET request over JSONP, and allows us to navigate around the single origin policy. The CRUD activity of our application is provided using shared access signatures, and writing to the Blob Store directly. You only use compute resource to decide which blobs the Client can read or write to. For data heavy applications this could make a massive difference. Your Azure compute time needs only to be sent servicing lightweight requests for permission, and not transferring data.
This is all very theoretical at the moment. I’ll report back with a working example!