I blogged several months ago saying that I was unsure of the real value of PaaS's. I continue to have these doubts, and we have recently being doing some experiments to explore life without a PaaS.
One bit of good news about PaaSes is that they are not platforms in the same sense as software like JEE application servers, or CICS or IMS. Those older platforms dictated the programming model of your application, and maybe even the application development language, so once you were on one, getting off it was hard. PaaSes like CloudFoundry, OpenShift and Heroku are really about deployment automation (and maybe subsequent management) along with infrastructure set-up and configuration. To me, PaaSes are more a way of packaging up DevOps, rather than a middle-ware platform. Your application does not run “on” them, rather it runs “in” an infrastructure environment they set up on your behalf (out of standard open-source parts), and then they help you get your application “into” that environment. What your application actually runs “on” is a language run-time, like Python, Ruby, or Node.js, which you select, along with some sort of very low-level application server like uWSGI or (G)Unicorn that is invisible to you. Because of this, we have had little difficulty moving our application between different PaaSes over time without making a single line of change to the application. [This description might be less accurate for the Google App Engine, which has more impact on the application programming model.]
Having a PaaS select and configure the infrastructure for you and deploy your application into it is handy, because it saves you learning how to do it for yourself. The down-side is that you have to live with their choices, and those choices have fairly fundamental implications for how your system will run. For example, all the PaaSes we've looked at (except maybe GAE) will deploy and configure your choice of database management system, but they all (including GAE) assume a simple model where each application has its own database. If you want to share a database between applications, you have to engineer that yourself, for example by setting up the database as an external service and accessing it from your applications. As another example, the deployment process of the PaaSes we've looked at stops the application, refreshes the hosting infrastructure, builds the application in-situ, then restarts the application. You might prefer to deploy a new version in production in parallel with the old one, divert increasing portions of traffic to the new version until you are confident it works well, and then retire the old one. We don't see any straightforward way of doing that with the current PaaSes. We have also seen quite a bit of instability when working with the PaaSes - things that used to work have stopped working on various occasions. Some of this might settle down as the PaaSes mature, but the PaaSes are also continually chasing the evolution of the infrastructure stacks they set up for you, so it's not clear whether this problem will go away completely.
If depending on a PaaS for deploying your application has drawbacks, the obvious question is, “How hard is it to just do it yourself?” We probably don't know enough yet to answer with complete conviction, but what we have seen so far is that it is remarkably simple, but not necessarily easy, depending on your skills. We have recently written our own software to set up an environment on Amazon EC2 and deploy our applications to it. Being minimalists, we chose not to use any of the more elaborate frameworks that claim to help you do this – we just wrote a few shell scripts. We also chose to start from a basic Linux distribution, rather than a more complex virtual machine image that had been built up by someone else. Remarkably, the whole thing – shell scripts plus various static configuration files or templates - comes out at only about 200 lines of source. [50 lines of that was writing an entire web server in shell script for the build machine so we didn't have to install and configure Apache - fun, but maybe not really very practical.] This overall size will probably grow a bit as we refine it, but it already implements a process that is in some ways more sophisticated than the one we see in the PaaSes. For example, rather than doing the application build as part of the deploy script, our process first produces a Linux package from the application build and then simply consumes that pre-built package during deployment. While the size of the source that implements this process is remarkably small, it wasn't necessarily easy to produce, and in fact Frank and I spent over a week doing it together. The hardest part was actually deciding the top-level design and flows - for example, where and when things run, where inputs and outputs are stored, who kicks things off, how you monitor progress and get error messages and so on. Another significant effort was picking infrastructure components (e.g. nginx, uWSGI) and learning how to configuring them. Lastly, if you are a beginner at Linux shell scripting as I am, the mechanics of writing and debugging these script are quite time-consuming and frustrating. A competent ops person who knew shell scripting and knew the infrastructure components to pick and how to configure them would probably have torn through the whole thing in a day or so. I do not claim that our scripts replicate all the value of a PaaS – I'm sure we still have a lot to learn about that – but I think it's interesting how much can be done with so little code.
Now that we have some scripts that liberate us from the tyranny of PaaSes, we're looking forward to exploiting our new freedom. We have not yet implemented the “rolling upgrade” strategy I described above, but we're anxious to do so. I'd also like to explore doing A/B testing by comparing two versions, rather than by inserting A/B comparison code into the application itself. We are also now in a position to have multiple applications access the same database without having to flip to a different deployment topology.