Azure Web Sites Shared has a New Quota Limit

Azure Web Sites Shared appear to have implemented a new usage quota based on your CPU usage over a 12 hour period.  This is new – previously there was a maximum CPU usage per hour but not one over a 12 hour period.

Once it has been exceeded, your web site becomes unavailable.  It also doesn’t seem to scale based on the number of instances you’re using (unlike memory which does) so this means that scaling out instances doesn’t help.  This WordPress blog running with 15K visits per month has exceeded this quota a couple times this month.

I’ve upgraded this blog to Basic Small which is about $60 / month instead of $10 / month per instance.

Read More

Microsoft Launches Azure App Service

Microsoft today launched a new Azure service called Azure App Service that integrates Azure Web Sites, Azure Mobile Services and Azure BizTalk Services into an integrated service. 

The new Azure App Services platform allows you to create Web Apps, Mobile Apps and Logic Apps within a single service.   Here is a collection of information on the new services.

New Pricing/Billing/Scale Model

Azure App Services is an integration of existing services from Azure with some new features and a new billing model.

From a billing perspective, if you were running Azure Web Sites, Azure Mobile Services or Azure BizTalk Services these are now integrated together into a single “Azure Service Plan”.  You can create multiple “apps” that all reside within a single plan so from a pricing perspective you’re charged only for that plan running in whatever scale you like instead of each different service having its own billing model. 

The tiered pricing is the same as the only Azure Web Sites model with Free, Shared, Basic and Premium tiers.  However, because you can now run multiple services on a single plan, you can leverage a consolidated price per instance.

In addition, each of these tiers now has additional quotas for things like API calls to connectors.

Azure Web Site is now Azure Web App

If you’re running an Azure Web Site, it has now been migrated to an Azure Web App running within an Azure App Service.   Azure Web Sites is no longer a stand alone service, unlike Azure Mobile and Azure BizTalk.

Azure Mobile Services is now Azure Mobile Apps

Azure Mobile Apps takes Azure Mobile Services and adds some new features.  Azure Mobile Services is still available as a standalone service because Azure Mobile Apps are still in Preview mode.

There are a number of new capabilities with Azure Mobile Apps including:

  • Staging slots for deployment

  • WebJobs
  • Traffic Manager Support
  • Better Scale Options

These services have been part of Azure Web Sites for a while and now are extended into the Azure Mobile Service as they become integrated into the new service.

Azure Logic Apps – Brand New Service

Logic Apps represent a cloud based business process workflow solution for orchestrations across Azure services and external SAAS services.  Logic Apps act as a distributed business process workflow solution that can integrate activities, actions and triggers across cloud services. 

The connectors available include the key Azure services as well as external services.

In addition, you can use standard web protocols such as FTP, HTTP, SMTP, etc. to trigger actions or send messages within your workflow.

API Apps – Create Your Own APIs and Monetize Them

The connectors above are a type of the new API App.  API Apps allow you to create your own APIs and monetize them.  You can write APIs using a variety of technologies (ASP.NET, Java, Node.JS, Python) and you can leverage the existing APIs and connectors provided by Microsoft to create super APIs that integrate and extend these existing connections.

Your APIs can be published to a gallery that can be either private to your organization or public to be consumed by third party developers.  The Azure Marketplace now supports selling of APIs as a new service for partners.

New Azure API Tools for Visual Studio

With all these new services, there is also a new Azure SDK that supports these new tools.  This includes creating new Azure API App templates and a new API App consumption feature that generates client code for accessing the APIs automatically for you. 

Add Client Dialog

Solution Explorer With Generated Code

Read More

Azure Web Sites Shared No Longer Scales Instances in Azure App Service

As part of the launch of the new Azure App Service, all your existing web sites from Azure Web Sites are now migrated to Azure App Service plans.  In my case, because I was running my web site on 2 Shared instances, it migrated each instance to a separate app service plan – Default 1 and Default 2 (there doesn’t seem to be any way to rename these plans at the moment).

In the old Azure portal, you can manually scale up or down the number of instances from 1 to 10 in Shared mode. 


However, at least in Shared mode, this scaling up/down capability has now been removed – you are limited to a single instance. 

However, if you go to the old portal (e.g. portal) you can still scale up or down and it works the same as before.

Read More

Application Insight Monitoring Now Supports Java based Web Apps

Microsoft has just released an SDK for integration the Application Insights Service into Java web based applications.

The Application Insights Service is a full monitoring solution for your web applications built into Azure Web Sites.  It is one of the compelling reasons to use Azure Web Sites over a traditional IAAS based solution.

With the Java SDK you can now instrument your Java based web application code and send telemetry data to Application Insights.  The instrumentation you can sending includes server based method calls, client interactions with your web site, and web tests.  You can also send your web logs to Application Insights for reporting, slicing and dicing.

To add the SDK to your project, you can use Eclipse and the latest version of the Azure Toolkit for Eclipse and you can right click on your project and configure Application Insights from your Java project.   Check out the getting started documentation here.

Application health

Usage Analytics

Metrics Explorer

Read More

Shrink Your WordPress Azure Web Site Memory Usage by Switching Comments Form to Disqus

As traffic on this web site has increased, the memory usage on Azure Web Sites has been creeping up, overwhelming the quotas on my Shared plan.  A Shared Instance of Azure Web Sites is allocated 512 MB of “memory usage” per hour which can be overwhelmed quickly if you get a reasonable amount of traffic.


One simple way to increase your quota is to scale up the number of instances – each new instance also increases your quota.  In my current configuration, runs on 2 shared instances which provides me a quota of 1024 MB / hour.   I have scaled this up to 3 instances when there has been noticeably higher traffic. 

One of the ways I have found to keep this usage contained is a pretty simple one – I switched my comments form to Disqus.  I was receiving approximately 500-1000 comments a day that were all spam which I’m convinced was increasing the load on my web site by at least 50-100%.  Switching to Disqus has killed the spam entirely and more importantly completely offloads comments to another service. 

Turning on Disqus is pretty easy in WordPress – just sign up for an account and then install the disqus plugin and it will replace your default WordPress comment form.

Read More

Integrating WordPress with Azure Search Service

This blog runs on WordPress using the Brandoo WordPress Plugin.  One of the key challenges with the Brandoo plugin is that the default search service doesn’t work.  I decided to build my own using Azure WebJobs, Azure Search Service and the WordPress REST JSON API.  Here are my lessons learned from developing an Azure Search Solution. 

Note: you can find all the code from the sample solution in GitHub here.

Getting Started

In order to integrate WordPress and Azure Search, the basic flow for data is:


In order to pull posts from WordPress, install the JSON REST API plugin found here (or in the plugin gallery). 

To create a custom WebJob, use the latest Azure SDK and Visual Studio 2013.  Once you have installed the Azure SDK, you’ll see a project template for Azure WebJobs. 

To use the Azure Search service, you need to create a search service in Azure.  See this article for directions on how to do this through the Azure Portal.

To access the Azure Search API, you can go through the REST API directly, or you can use the RedDog.Search C# client.  To install the client into your WebJob, you run the NuGet package console and enter “Install-Package RedDog.Search”.  This also installs the NewtonSoft JSON.NET library which we can also use for interacting with the WordPress REST API.

WebJobs Architecture

When you create a WebJob in Visual Studio, it provides the ability to deploy straight to your Azure Web Site.  This works really well.  Alternatively, you can upload it manually as an .exe through the portal.  You can also run your WebJob locally in debug mode which in this case works perfectly because we have no real dependencies on Azure Web Sites to run the job.

The basic components of the architecture are:

  • Program: the main web job console app.
  • WordPressJSONLoader: service class responsible for pulling posts from WordPress
  • WordPressPosts and WordPressPost: value objects representing the loaded collection of wordpress posts and each individual post.
  • AzureSearchIndexer: service class responsible for pushing posts into Azure Search.

Runtime configuration is done through the App.config and/or the Azure Web Sites configuration.  As part of the Azure SDK you can use the CloudConfigurationManager to get environment settings and it is smart enough to use values in the Azure Web Sites configuration as priority over any settings found locally in the App.Config.  If you are running locally, it degrades automatically to looking in your App.Config for configuration values. 

// load configuration attributes webSiteURL = CloudConfigurationManager.GetSetting("WebSiteURL"); searchServiceName = CloudConfigurationManager.GetSetting("ServiceName"); searchServiceKey = CloudConfigurationManager.GetSetting("ServiceKey"); indexName = CloudConfigurationManager.GetSetting("IndexName");

Retrieving Posts from WordPress

With the JSON REST API plugin installed, retrieving posts from WordPress is easy – just call the URL  This will by default retrieve the last 10 posts but you can use filtering parameters and paging to change how many posts you retrieve.

Using the JSON.API library, you can deserialize your JSON into a JObject which provides you an easy way to pull entities such as posts, comments, etc. out of the returned JSON.

When the JSON REST API is called, it provides 10 posts and the number of “pages”.  Based on this number of pages, we can pull all the posts 10 posts at a time.

public static WordPressPosts LoadAllPosts(string URL) { try { WordPressPosts wordPressPosts = new WordPressPosts(); string query = "?json=get_posts"; WebClient client = new WebClient(); Stream stream = client.OpenRead(URL + query); StreamReader reader = new StreamReader(stream); var results = JObject.Parse(reader.ReadLine()); var JsonPosts = results["posts"]; if (JsonPosts != null) { foreach (var JsonPost in JsonPosts) { wordPressPosts.Posts.Add(loadPostFromJToken(JsonPost)); } } if (results["pages"] != null) { int pages = (int)results["pages"]; if (pages > 1) { for (int i = 2; i <= pages; i++) { query = "?json=get_posts&page=" + i; stream = client.OpenRead(URL + query); reader = new StreamReader(stream); results = JObject.Parse(reader.ReadLine()); JsonPosts = results["posts"]; foreach (var JsonPost in JsonPosts) { wordPressPosts.Posts.Add(loadPostFromJToken(JsonPost)); } } } } return wordPressPosts; } catch (Exception e) { throw; } }

In this method, we simply pull out the posts and deserialize these to a collection of WordPressPost objects. 

Running Async Tasks in Console Apps

The library contains only the new .NET 4.5 async methods.  You need to be careful to wrap these methods so that your console app doesn’t delegate out to these methods and then end the program prematurely.  The way to achieve this is to create an async method that you execute from your main program and wait for it using the Wait() method.

You can then call this method from Main() like this:

In addition, make sure that all your async methods return Task instead of void as this will cause your console app to prematurely exit.

Checking for Errors

In the RedDog.Search library, you call all its methods like this:

public async Task CreateIndex() { // check to see if index exists. If not, then create it. var result = await managementClient.GetIndexAsync(Index); if (!result.IsSuccess) { result = await managementClient.CreateIndexAsync(new Index(Index) .WithStringField("Id", f => f.IsKey().IsRetrievable()) .WithStringField("Title", f => f.IsRetrievable().IsSearchable()) .WithStringField("Content", f => f.IsSearchable().IsRetrievable()) .WithStringField("Excerpt", f => f.IsRetrievable()) .WithDateTimeField("CreateDate", f => f.IsRetrievable().IsSortable().IsFilterable().IsFacetable()) .WithDateTimeField("ModifiedDate", f => f.IsRetrievable().IsSortable().IsFilterable().IsFacetable()) .WithStringField("CreateDateAsString", f => f.IsSearchable().IsRetrievable().IsFilterable()) .WithStringField("ModifiedDateAsString", f => f.IsSearchable().IsRetrievable().IsFilterable()) .WithStringField("Author", f=>f.IsSearchable().IsRetrievable().IsFilterable()) .WithStringField("Categories", f => f.IsSearchable().IsRetrievable()) .WithStringField("Tags", f => f.IsSearchable().IsRetrievable()) .WithStringField("Slug", f => f.IsRetrievable()) .WithIntegerField("CommentCount", f => f.IsRetrievable()) .WithStringField("CommentContent", f=>f.IsSearchable().IsRetrievable()) ); if (!result.IsSuccess) { Console.Out.WriteLine(result.Error.Message); } } }

The result will provide a status of success and in the case of an error, some important error details.   Anything that is written to the Console is redirected into the Azure Web Sites log for the WebJob.

Creating an Index

Creating an index is reasonably easy but I found a few gotchas along the way:

  • The key field MUST be a string (I originally tried to use an integer field).
  • Searchable fields MUST be of type string (I originally tried to make a date field searchable). 

If you try to violate the rules, the Index creation process fails and the result returned will be an error.

Adding Posts to an Index

Now that we have our index, we can push posts into the index.

foreach (WordPressPost post in WordPressPosts.Posts) { IndexOperation indexOperation = new IndexOperation(IndexOperationType.MergeOrUpload, "Id", post.Id.ToString()) .WithProperty("Title", post.Title) .WithProperty("Content", post.Content) .WithProperty("Excerpt", post.Excerpt) .WithProperty("CreateDate", post.CreateDate.ToUniversalTime()) .WithProperty("ModifiedDate", post.ModifiedDate.ToUniversalTime()) .WithProperty("CreateDateAsString", post.CreateDate.ToLongDateString()) .WithProperty("ModifiedDateAsString", post.ModifiedDate.ToLongDateString()); IndexOperationList.Add(indexOperation); } var result = await managementClient.PopulateAsync(Index, IndexOperationList.ToArray() ); if (!result.IsSuccess) Console.Out.WriteLine(result.Error.Message); foreach (WordPressPost post in WordPressPosts.Posts) { IndexOperation indexOperation = new IndexOperation(IndexOperationType.MergeOrUpload, "Id", post.Id.ToString()) .WithProperty("Title", post.Title) .WithProperty("Content", post.Content) .WithProperty("Excerpt", post.Excerpt) .WithProperty("CreateDate", post.CreateDate.ToUniversalTime()) .WithProperty("ModifiedDate", post.ModifiedDate.ToUniversalTime()) .WithProperty("CreateDateAsString", post.CreateDate.ToLongDateString()) .WithProperty("ModifiedDateAsString", post.ModifiedDate.ToLongDateString()); IndexOperationList.Add(indexOperation); } var result = await managementClient.PopulateAsync(Index, IndexOperationList.ToArray() ); if (!result.IsSuccess) Console.Out.WriteLine(result.Error.Message);

One key gotcha on adding items to the index – the date field must be in UniversalTime or you’ll get an error message.   For example, instead of supplying post.ModifiedDate as a DateTime attribute you need to call post.ModifiedDate.ToUniversalTime() or the index operation will generate an error.

The RedDog.Search PopulateAsync method allows you to add multiple IndexOperations objects that store up your document post requests into a batch.  The maximum number of IndexOperations the library supports is 1,000 or 16 MB.  In our method, we limit the number of posts per batch to 100 posts to be well under this limit.

public async Task AddPosts() { // if not previously connected, make a connection if (!connected) Connect(); // create the index if it hasn't already been created. await CreateIndex(); // run index population in batches. The Reddog.Search client maxes out at 1000 operations or about 16 MB of data transfer, so we have set the maximum to 100 posts in a batch to be conservative. int batchCount = 0; List<IndexOperation> IndexOperationList = new List<IndexOperation>(maximumNumberOfDocumentsPerBatch); foreach (WordPressPost post in WordPressPosts.Posts) { batchCount++; // create an indexoperation with the appropriate metadata and supply it with the incoming WordPress post IndexOperation indexOperation = new IndexOperation(IndexOperationType.MergeOrUpload, "Id", post.Id.ToString()) .WithProperty("Title", post.Title) .WithProperty("Content", post.Content) .WithProperty("Excerpt", post.Excerpt) .WithProperty("CreateDate", post.CreateDate.ToUniversalTime()) .WithProperty("ModifiedDate", post.ModifiedDate.ToUniversalTime()) .WithProperty("CreateDateAsString", post.CreateDate.ToLongDateString()) .WithProperty("ModifiedDateAsString", post.ModifiedDate.ToLongDateString()) .WithProperty("Author", post.Author) .WithProperty("Categories", post.Categories) .WithProperty("Tags", post.Tags) .WithProperty("Slug", post.Slug) .WithProperty("CommentCount", post.CommentCount) .WithProperty("CommentContent", post.CommentContent); // add the index operation to the collection IndexOperationList.Add(indexOperation); // if we have added maximum number of documents per batch, add the collection of operations to the index and then reset the collection to add a new batch. if (batchCount >= maximumNumberOfDocumentsPerBatch) { var result = await managementClient.PopulateAsync(Index, IndexOperationList.ToArray()); if (!result.IsSuccess) Console.Out.WriteLine(result.Error.Message); batchCount = 0; IndexOperationList = new List<IndexOperation>(maximumNumberOfDocumentsPerBatch); } } // look for any remaining items that have not yet been added to the index. var remainingResult = await managementClient.PopulateAsync(Index, IndexOperationList.ToArray() ); if (!remainingResult.IsSuccess) Console.Out.WriteLine(remainingResult.Error.Message); }

Now that we have our index, we can push posts into the index.

Checking our Index in the Portal

We can verify that we have content in the index by going to the portal and checking out our index:


As shown, we have a newly created index with 291 items in it.

Building a Search Portal

Now that we have some content, let’s build a simple search interface using just HTML and JavaScript.  We’ll use the REST APIs to fetch data from the index and display the search results using Angular.JS as a framework.

Publishing to Azure Web Sites into a Virtual Application

Our WordPress site has been installed into the root of the Azure Web Site.  When we publish our search pages and JavaScript code, we don’t want them clobbering our existing WordPress site or getting deleted or mangled by mistake if there is an upgrade to WordPress.

Azure Web Sites supports the addition of virtual applications that run in their own sub-directory.  To create one, go into the Configure tab of the Azure Web Site and go to the bottom of the page.  You will see a section called “virtual applications and directories”.  In here, we can create a completely separate application that runs in its own directory, with its own web.config and publishing profile.


In Visual Studio, you can configure the publishing profile to publish to this new virtual application.


Specify the subdirectory in both the Site Name and Destination URL fields.

Fetching the Search Results With AngularJS

Building a search form using AngularJS is ideal for pulling in data from Azure Search because Azure Search returns JSON data by default.  We can simply assign the results to an AngularJS variable and then use the AngularJS framework to display the results dynamically.

We start with a basic Search form styled using Bootstrap.  I use the Sparkling Theme for my WordPress blog and this them already uses Bootstrap as its core CSS framework so adding in some custom HTML using the same Bootstrap CSS elements works really well.


The nice thing with using Bootstrap is that if you switch your WordPress theme, as long as it uses Bootstrap (most of them do these days) your search form and results will take on the style of your blog.

If you perform a search with no keywords specified, Azure Search will return ALL documents.  This isn’t something we would want so we have made keyword a required field and check to ensure it isn’t blank before submitting.

The submit method for fetching the Azure Search results is the key for pulling in the results from Azure Search.  In building this method, I found a few gotchas to share:

  • Make sure you include the api-version in the request or Azure Request will return an error.
  • The default order by is relevance.  In our case, we have also added an additional option to sort by Create Date (e.g. $orderby=CreateDate desc.
  • You have to include the api-key in the HTTP header when you send in the request.  You can create a Query key in the azure portal instead of using the admin key and having it public.
  • You assign the JSON object “value” – this contains the search results.
vm.submit = function (item, event) { if (vm.orderby == "Relevance") var URLstring = vm.URL + "?search=" + vm.keywords + "&api-version=" + vm.APIVersion; else var URLstring = vm.URL + "?search=" + vm.keywords + "&$orderby=CreateDate desc" + "&api-version=" + vm.APIVersion; if (!isEmpty(vm.keywords)) { var responsePromise = $http.get(URLstring, config, {}); responsePromise.success(function (dataFromServer, status, headers, config) { vm.results = dataFromServer.value; vm.showSearchResults = true; }); responsePromise.error(function (data, status, headers, config) { alert("Submitting form failed!"); }); } else { vm.showSearchResults = false; vm.results = []; } }

Displaying the Results

Once we have a JSON object with the search results, displaying them is pretty easy – just use the AngularJS ng-repeat attribute to iterate through the results returned.

<div ng-repeat="result in search.results"> <a class="h1" href="{{result.Id}}">{{result.Title}}</a> <div class="h6" ng-bind-html="result.CreateDateAsString | unsafe"></div> <div ng-bind-html="result.Excerpt | unsafe"></div> </div>

One key note is the use of a filter to treat the HTML returned as HTML – by default AngularJS will HTML encode the HTML instead of letting it through raw.  In order to change this behaviour, you can add this function:

angular.module('app').filter('unsafe', function ($sce) { return function (val) { return $sce.trustAsHtml(val); }; });

Using this filter you can then declare the variable as unsafe and it will be allowed through as raw HTML.

Adding a link to the original post is easy – just create an anchor link with the ID of the post.  (You could also use the slug variable that is indexed if permalinks are turned on for more friendly URL’s).

Integrating into WordPress

With the solution published to Azure Web Sites into a Search subdirectory, we can use the published JavaScript files and embed them into our WordPress site.  While a proper WordPress plugin would be ideal, we just added the search.html code into a WordPress page using the out of the box content editor.

Note: when adding HTML into a page using the text editor in WordPress, if you lead any line feeds WordPress converts them into <p> tags.  This isn’t what we want with all our javascript and AngularJS code.  If you delete all the line feeds and keep all the HTML together, you can mitigate this problem.


The Final Result – Search Results!

Here is the final result – a fully functioning search page that pulls WordPress posts from Azure Search and searches against keywords with the results sorted by either relevance or create date.


Read More

Publishing to Azure Web Sites with Multiple Virtual Applications

Azure Web Sites supports the addition of virtual applications that run in their own sub-directory.  By default, your main web application is in the root directory.  You can create a new application that is isolated to its own sub-directory and with its own web.config.

To create a new virtual application, go to the Configure tab of the Azure Web Site and go to the bottom of the page.  You will see a section called “virtual applications and directories”.  In here, we can create a completely separate application that runs in its own directory, with its own web.config and publishing profile.


In Visual Studio, you can configure the publishing profile to publish to this new virtual application.  Just make sure to specify the subdirectory in both the Site Name and Destination URL fields.

Read More

Warning: Azure Web Sites Turning Off PHP 5.3 Support on January 31, 2015

I just received an email from Microsoft that informs me that PHP support for version 5.3 will be turned off as of January 31, 2015.  All Azure Web Sites will now only support the upgraded 5.4 version of PHP.

For those of you using PHP to run your web site, check for 5.4 compatibility before the end of the month!


Read More

Application Insights is Yet Another Reason to Use Azure Web Sites!

As posted previously, hosting a web site can be easily done using IAAS services.  Create your own VMs and you can host PHP, MySQL, .NET or any other type of web application.  However, now you have to patch your VM, upgrade all the software, monitor it, back it up, etc.

This is where Azure Web Sites is such a compelling offering – if you’re running an ASP.NET, PHP, Java, Python or Node.JS you can deploy your site and have Microsoft manage the infrastructure for you.  In addition, you now get auto-scaling up to 10 instances of your web site and access to a number of different storage options including SQL Server, Azure Document DB, Mongo DB, Azure SQL, Blob Storage, etc.

As part of Azure Web Sites, Microsoft is now including a full monitoring solution called Application Insights at no extra cost.  You can turn it on through the portal or you can enable it when you create your web site in development using Visual Studio.

Application Insights not only monitors your web site  but auto-discovers dependencies such as the underlying database and monitors those as well.

Read More

Brandoo Plugin for WordPress NOT Recommended on Azure Web Sites

As posted previously, this blog currently runs on WordPress and recently I migrated the blog to Azure SQL using the Brandoo Plugin.

The primary reason to migrate was that I don’t like the ClearDB MySQL database option as the free version is limited to 4 connections and the paid version is not cheap and/or scalable as running Azure SQL.  I really want to have a site that can run as light weight as possible to recommend to people looking for low cost approaches for running sites on Azure Web Sites.

Unfortunately, it seems that the Brandoo project has run into a lot of challenges with the ongoing changes in WordPress.  I heard from the Brandoo project owner himself:

Hello Christopher,
I’m the maintainer of Brandoo WordPress. Changes in WordPress upstream is making debugging of Brandoo WordPress almost impossible today. There is many “strange” changes in WordPress, making translation to AzureSQL/MS SQL impossible at all. We do not want to change WordPress core and build fork. Without community we will be not able to work on it. There is no support form developers community so we are fighting alone. Second thing is that today it is possible to connect Azure Web Site with Your own MySQL cluster or single VM via VPN. So You can create HA WordPress on Azure without AzureSQL – I think that this will be a new direction for Brandoo WordPress. I’m father of this project and it is not so simple to tell You, that we are slowly going to the end of Brandoo WordPress in form You know and use.
Best Regards,

What this means is that if running Brandoo is a use at your own risk option.  While my experience has been positive so far (except for search not working), it means that it’s not a well supported option and one that I couldn’t recommend as a solution to those wanting to run a low cost web site or blog on Azure Web Sites.

My next step for this blog is to look at alternatives to WordPress that will work on a standard Azure Web Site with an Azure SQL database (or even better, no database requirement at all).  I’ll keep everyone posted as I look at various options – currently I’m looking at C1 Composite, Ghost, and a few others (I’ve ruled out both Joomla an Drupal as they don’t seem to deploy properly to Azure SQL).

Read More