21st January, 2012
Several months ago I wrote a prototype backend for a software-as-a-service product in a fairly unusual manner. The languages and frameworks I know best are C and Objective-C/Cocoa and so this is where I am most productive. The prototype was up and running in a very short space of time and fulfilled its primary goals which I list below.
The product was extremely fast due to the use of carefully constructed C data structures and keeping all data in memory. Performance was over five orders of magnitude greater than the benchmark product.
Low System Requirements
Due to keeping all data in memory, the system is bound by RAM. However, through some normalisation, a typical instance for a medium sized company would consume about 15MB of RAM including the web server and database server. In memory compression could drastically reduce this if it became a bottleneck.
Event Sourcing and CQRS
The whole system uses event sourcing and can be rewound to any point in time. Scope was left for decoupling commands and queries for CQRS but due to the speed of the system this wasn’t required at this stage.
Using zero-configuration networking and distributed objects any number of application instances on the same network will automatically discover each other and replicate events amongst themselves. An alternative method of forwarding events over HTTP is included to bridge different networks.
The main issues that I encountered while creating this system were in deployment. It’s actually pretty difficult to find a good way to deploy ObjC web applications, especially outside of a Mac OS X environment. On top of this, Mac OS X hosting is much rarer and more expensive than Linux hosting. I investigated many options including WebAppKit, Bombaxtic, FrothKit, WebObjects on GnuStep, SOPE, cgic, Cocotron and more. I found every option lacking. Bombaxtic and FrothKit have been abandoned, WebAppKit is too young, GnuStep is stepping into uncomfortable development territory, Cocotron lacks an NSDecimalNumber implementation and cgic feels too much like re-inventing the wheel.
For a long time I have been meaning to learn Python and/or Ruby. I decided this would be the perfect opportunity and have started porting the prototype application from Objective-C to Ruby as a learning project. I imagine that the implementation will be a few orders of magnitude slower but I will be interested to get quantitative results. It should still be significantly faster than the benchmark.
I’ve been impressed by the terseness of Ruby although I miss the static typing of the Objective-C world. I find the RubyGems system to be excellent and am using various gems for decimal numbers (FLT), http interfacing (Sinatra), CSV parsing, JSON encoding, WebSockets and Redis integration. I’ve also made use of Heroku’s free starter packages to deploy the application on the web and have been blown away at the possibilities that a platform-as-a-service offers.
For zero monetary outlay I have my application and web front-end hosted online. I have SSL and websockets for realtime updates and a free Redis instance. I can add free SMS messaging, email sending, memcached and HTML to PDF/XLS conversion. And to deploy the application all I need to do is push from my local git repository to heroku’s remote. The possibilities are staggering. To have these services for free necessarily entails them being subject to quite restrictive service levels or throughput, but to be able to create something so scalable and so easily is quite mind blowing. No longer do you require a VPS and expertise in setting up, securing and maintaining multiple pieces of infrastructure. For practically nothing (a few hundred dollars per month) you can launch your product with decent service levels once you have it all working. If it takes off and you’re in the fortunate situation to have so many users that heroku is costing too much, you can then migrate away to your own servers as there is no lock in and it’s an open stack.
The barrier to entry has been significantly lowered.