Saturday, November 23, 2013

Windows Azure SQL Databases, Cost Effective or Not?

Last week I gave an Windows Azure presentation at Modern Apps Live in Orlando.  The session itself wasn't well attended and that matches many of my past experiences with Azure presentations.  I spoke to several people afterwards and it seems that much of the disinterest around Azure has to do with its perceived high cost when comparing it to alternatives.

To some extent this is Microsoft's fault, when they came out with the service initially it wasn't all that well priced.  But for the most part that has changed and Azure is a much better deal than people realize, particularly when looking at factors around redundancy.  For example, there are few ways to quickly and cheaply get a redundant T-SQL database up than by using a Windows Azure SQL Database (WASD).

Companies usually have about three options here.  They can use a private cloud (either existing or build a new one), they can use some sort of IAAS provider like Rackspace (or use Azure IAAS), or they can use a PAAS like WASD.

The private cloud cost comparison is harder to quantify as there are so many situational specific factors that need to be understood in the calculation.  It is usually true that for companies who have existing private clouds it is cheaper to leverage a sunk investment than to move to an IAAS or PAAS SQL solution in the short term.  I want to reiterate; in the short term.  That is because in the short term much of the cost involved in creating that private cloud is sunk.  In the long term (five year horizon) that calculation may change as hardware needs to be refreshed and the amount of services  you plan on deploying to your private cloud will influence the amount of hardware you will need to keep up to date to continue your private cloud investment.  This is an area where momentum tends to come into play that is to say, the path of least resistance is for IT managers to continue to refresh their private cloud infrastructure than to come up with a plan for moving a portion of their services into a hybrid cloud.

In general, if you have a private cloud and want to do a long term analysis on the benefits of moving SQL Services to a hybrid or public cloud these are some of the factors you want to keep in mind.
  • If I move some of my services to a hybrid/public cloud what will my data transfer services cost me in the cloud vs. how much do they cost me now?  Corollary to this is the question of should I move applications that use the data into the cloud as well to limit that data transfer cost?  Remember, to do an apples to apples comparison here, moving around data on your current infrastructure has an associated cost as well (hardware to deal with the amount of data flowing through the network, dark fiber between facilities, external lines that have a data charge for lighting buildings or employees in the field, etc.)  The cost of data transfer is most likely the greatest single monetary factor in this equation.
  • If you move some portion of your services to the cloud, can you do a lower investment in hardware in your private cloud due to the lower need for services in your own facilities?
  • What kind of data do you have and what are the risks between maintaining it in different locations?  The common example is that HIPPA generally is not used in public clouds, though Azure has been working on solutions for that too: http://www.eweek.com/c/a/Health-Care-IT/Microsoft-Adds-HIPAA-Compliance-in-Windows-Azure-for-Cloud-Health-Data-446671/
  • Do I need to have a solution with geographically diverse databases and if so, what are my requirements behind how often the data needs to be kept in sync?  WASD can be set up in many different geographic regions and kept in sync, over time.  The sync interval can be set as low as every five minutes but due to the hub and spoke model even that may take as long as 10 minutes for data changes to be distributed from one spoke to another.
  • How much does your OS licensing cost you?
  • Can the applications that use the database use SQL security instead of Windows integrated security?  WASD only supports the SQL security model.
  • How much does your infrastructure cost you and what are the opportunity costs associated with having infrastructure personnel working machines with SQL databases instead of the many other mission critical items they could be focusing on?  Do you need the same amount of infrastructure resources, particularly as the company grows, etc.?
  • Do you have SLA requirements?  Currently the WASD offer 99.9% monthly uptime.  Many companies require more. Having said that, in my experience very few companies actually maintain greater than 99.9% when doing an analysis of their internal data center operations.  This is an area where companies may have to analyze what their internal capabilities really are.
  • What are your redundancy requirements?  This is one where WASD are hard to beat and give a benefit few people recognize.  If you have an instance of a WASD in a Azure data center you are getting that plus three redundant instances; one primary redundant instance and two secondary.  If your main instance, or one (or more) of the redundant instances go down, Azure will use the others to continue uninterrupted service and bring up more redundant instances in the background.  The net effect is that it is very difficult to take down a WASD instance without an entire data center or the Azure service in general going down (which has happened twice that I can recall).
One thing you may notice is missing from my list; that is DBAs.  You will likely need the same number of DBAs if you host your databases in your private cloud, in a public cloud through IAAS or using a PAAS offering like WASD.  We know comparing the cost of a private cloud is highly situational, but what about looking at IAAS vs. a PAAS like WASD?  That is much clearer, and in most cases WASD will be doing IAAS at a company like Rackspace.  If you've determined that moving a SQL Service instance from your internal private cloud to an IAAS service, in many cases it may be less expensive to take it one step further and go to WASD.

Let's look at this comparison.  For information about assumptions, we have about 60 GB of data of which our average outbound data per month is 2000 GB, increasing 10% yearly.  Also for the Rackspace offering we set up two servers is an active/passive SQL cluster to get some level of redundancy but still less than what we get with WASD.  If that's the case, we end up with something like this:

Windows Azure Year 1 Year 2 Year 3 Year 4 Year 5 Total
Cost WASD/Year $1,510.56 $1,570.44 $1,630.44 $1,690.32 $1,750.32 $8,152.08
Cost of outbound data $2,880.00 $3,168.00 $3,484.80 $3,833.28 $4,216.61 $17,582.69
Total $4,390.56 $4,738.44 $5,115.24 $5,523.60 $5,966.93 $25,734.77

IAAS (Rackspace) Year 1 Year 2 Year 3 Year 4 Year 5 Total
Cost of server licensing $155.40 $0.00 $0.00 $180.00 $0.00 $335.40
Cost of SQL licensing $678.00 $0.00 $0.00 $711.90 $0.00 $1,389.90
Cost of data center $1,401.60 $1,401.60 $1,401.60 $1,401.60 $1,401.60 $7,008.00
Cost of IT labor $480.00 $494.40 $509.23 $524.51 $540.24 $2,548.39
Cost of outbound data $2,880.00 $3,168.00 $3,484.80 $3,833.28 $4,216.61 $17,582.69
Total $5,595.00 $5,064.00 $5,395.63 $6,651.29 $6,158.45 $28,864.37

Of course there are many factors that can cause these numbers to change.  For example, we can say that the SQL instance doesn't need to be redundant like it is with WASD.  Also Rackspace's outgoing data charges decrease the more data you use while WA does not (perhaps something MS should change to stay competitive).  The point of the exercise is to realize that prima facie the Windows Azure services are not more expensive than competitive offerings.  The services offer other benefits that I have not mentioned here but they are worth doing a serious analysis on, both from a cost and a feature perspective.

If you do, or do not, think Windows Azure services are cost effective, or even if you don't know I'd be interesting in speaking with you.

Friday, November 1, 2013

Angular Promises in TypeScript

If you're like me and love typed languages, TypeScript seems like a great thing and it is.  Though there are some complications to using it along with some of the existing frameworks that are out there.  A lot of this comes from using modules and classes in TypeScript, which you probably are if you are using typeScript in the first place.  When using TypeScript and Angular it can sometimes be hard to get access to things like Angular's $scope deep within the bowels of your classes.

Recently I was working with Azure and handling the asynchronous request callback using an Angular promise.  This presented me with a couple of difficulties:

  • When calling .resolve on the deferral, it was never firing the .when statement on the code that was holding the promise so I never got may data loaded correctly from my factory
  • Inside the deferral callback code in a class, any calls to the classes properties using the 'this' operator were failing with an undefined or null reference error
What to do?  Here was my original non working code:

Calling code:
this.dataAccess.BeginGetRegistrations().then(function (result: Classes.RegistrationDTO[]) {
    for (var i in result) {
        var registrationDTO: Classes.RegistrationDTO = result[i];
        var registration: Registration = new Registration(registrationDTO.Id, this.dataAccess);
        registration.LoadRegistration(registrationDTO.ScreenName, registrationDTO.Email, registrationDTO.Zip, registrationDTO.Gender, registrationDTO.BirthDate);
        this.Add(registration);
    }
});

Asynchronous function in my data access class:
public BeginGetRegistrations(): ng.IPromise<Classes.RegistrationDTO[]>{
    var deferral = this.service.defer<Classes.RegistrationDTO[]>();
    var registrations = DataAccess.client.getTable('Registration');

    registrations.read().done(function (results) {
        var returnValue: Classes.RegistrationDTO[] = [];
        var registration: Classes.RegistrationDTO;
        for (var i in results) {
            var result = results[i];
            registration = current.LoadResult(result);
            returnValue.push(registration);
        }
        deferral.resolve(returnValue);
    }, function(err) {
        throw err.toString();
    });
    return deferral.promise;;
}

I did a little digging around it seemed obvious.  The call to resolve on the deferral needs to happen in a context that Angular is aware of.  In this case, calling resolve inside $apply method on the $rootScope should solve it so the .when statement on the calling code fires.  Since I was way down in the bowls of a class inside a module I had Angular inject the $rootScope into my factory which in turn set it inside my data access class on creation (constructor).  Now my data access class has a reference to the $rootScope in a class level variable called scope.

I rewrote my code hoping to get the .when to fire like this:
public BeginGetRegistrations(): ng.IPromise<Classes.RegistrationDTO[]>{
    var deferral = this.service.defer<Classes.RegistrationDTO[]>();
    var registrations = DataAccess.client.getTable('Registration');

    registrations.read().done(function (results) {
        var returnValue: Classes.RegistrationDTO[] = [];
        var registration: Classes.RegistrationDTO;
        for (var i in results) {
            var result = results[i];
            registration = current.LoadResult(result);
            returnValue.push(registration);
        }
        this.scope.$apply(deferral.resolve(returnValue));
    }, function(err) {
        throw err.toString();
    });
    return deferral.promise;;
}

As soon as I did this, the second problem raised its head.  That is, I couldn't get access to the 'this' keyword and was failing with an undefined or null reference.  This problem manifested in both the BeginGetRegistration method and the calling code.  The solution was simple.  In each of these methods set a local variable equal to the class level 'this' variable so the callback function has access to it and all was well with the world.  My new corrected and working functions:

Calling code:
var current: any = this;
this.dataAccess.BeginGetRegistrations().then(function (result: Classes.RegistrationDTO[]) {
    for (var i in result) {
        var registrationDTO = result[i];
        var registration: Registration = new Registration(registrationDTO.Id, current.dataAccess);
        registration.LoadRegistration(registrationDTO.ScreenName, registrationDTO.Email, registrationDTO.Zip, registrationDTO.Gender, registrationDTO.BirthDate);
        current.Add(registration);
    }
});

Asynchronous function in my data access class:
public BeginGetRegistrations(): ng.IPromise<Classes.RegistrationDTO[]>{
    var deferral = this.service.defer<Classes.RegistrationDTO[]>();
    var registrations = DataAccess.client.getTable('Registration');
    var current: any = this;

    registrations.read().done(function (results) {
        var returnValue: Classes.RegistrationDTO[] = [];
        var registration: Classes.RegistrationDTO;
        for (var i in results) {
            var result = results[i];
            registration = current.LoadResult(result);
            returnValue.push(registration);
        }
        current.scope.$apply(deferral.resolve(returnValue));
    }, function(err) {
        throw err.toString();
    });
    return deferral.promise;;
}

With these fixes in place my Azure mobile code was loading beautifully, asynchronously and Angular binding was handling the data coming back and displaying on the UI exactly as it should.