views:

51

answers:

2

Hello, I made a e-commerce app the runs on C#. Each instance of this app right now has it's own:

  1. IIS 7 app pool
  2. IIS 7 website
  3. SQL Server 2008 database

My partner told me that we need to dump this approach and move to a cloud. It seems like SQL Azure charges per database. So it will be very expensive for us to go this approach. Is there a way we can use a single giant database without having to re-write the entire data-access layer? *Or is there a cheap way to have hundreds of tiny SQL Azure databases?*

note: each database is only about 20 MB

+2  A: 

Yes, SQL Azure charges you per database, but what you're really paying for is the size of the database. For example a 1GB DB will cost you $9.99 and month, a 10GB DB will cost you $99.99 a month. The databases in SQL Azure also currently have a maximum size of 50GB.

Based on this and what you've said about your app (possibly hundreds of DBs), and making the assumption that each database is going to contain enough data to make paying for 1GB of DB worthwhile, I would continue to use one DB for each instance.

If the data for each instance is actually quite small and even if you had hundreds of instances you wouldn't hit the 50GB limit then you would save money (but not time) by partitioning your data and storing it in just one database.

If cost is your primary concern and you're thinking about a rewrite anyway, I would consider using Azure Table Storage (AZT) where that same 1GB of data will cost you $0.15 a month to store (but you do have to give up on little things like foreign keys and queries with more than 1 table in them)

knightpfhor
From a cost perspective [Azure Table Storage (AZT)] would be the best. However it would cause a major application re-write.
aron
There is also this sample from MS which is all about a multitenant systems. http://www.fabrikamshipping.com/
knightpfhor
+1  A: 

At 20MB per database, you'd cover about 50 such databases in a single 1GB Azure database.

With the new database sizes, your next size up is 5GB, and your billing is amortized on a daily basis, based on the maximum storage used for a given day. So, for the times when you're under 1GB, you're billed at the 1GB rate ($9.99 per month / days in month). Once you exceed 1GB, you move to the 5GB tier ($49.95 / days in month). This would be considerably less expensive than having 50 1GB databases, which would run approx. $500 monthly.

To combine your databases, you'd need some type of customer id or instance id that you'd have to add to your tables, to provide your partitioning across tenants.

I saw another suggestion by knightpfhor about moving to Table Storage for cost savings. While Table Storage is less expensive than SQL Azure storage, that would likely be a major application change, as Table Storage is non-relational and doesn't have stored procedures or any other support you'd normally get from SQL Server. Adding a partition / customer key is much less invasive than a wholesale storage-layer rewrite.

David Makogon
The term missing in this (excellent) answer is multi-tenancy; that makes it easier for the OP to bingoogle for background info. A multi tenant database would make sense in this scenario, but in general, a multi tenant app makes even more sense in terms of cloud scenarios.
tijmenvdk
My app allows en-users to upload C# code. So it's important the each site has it's own isolated db. That way if the upload some malicious SQL code it only effects their own db. Would a single azure db allow me to do this? Could I make a sub databases? or schemas where the end user's site's connection string has limited access?
aron
Is any of the code that is uploaded by the users run on your database? Are the users able to make changes to the database?
knightpfhor
If you're letting end-users upload code to your cloud-hosted app, you might have bigger problems than data access. If you do decide to let them upload code, you'd need to remove direct database access (don't expose database connection string or credentials); instead, route all data access through a data tier, with something like WCF (that's typically a good practice to follow anyway). With that in place, you'd never have to worry about malicious code reading from the wrong tables / rows. You'd still need some type of credentials per user that lets your data tier know their customer ID.
David Makogon
Keep in mind: end-user code could simply link with the Azure support DLLs. Think about malicious "runtime" code instead of malicious "SQL" code. Just consider a random call to RoleEnvironment.RequestRecycle() that will have you scratching your head, wondering why your role instances keep rebooting. Or maybe a little event handler registered to RoleEnvironment.Changing, that provides malicious code to do something inline with your app's configuration changes? Maybe this is too advanced: How about a tight loop that simply runs your worker role at 100% CPU.
David Makogon