An Azure Directory is not a resource. It lives outside the subscription, on its own.

Every Azure Subscription is linked to an Azure Directory as the place that it reads its identities from.

“Co-owner” is a security role applied at the Azure Subscription level, granting control of the resources within that subscription.

Generally, we should be granting less co-admin rights in the old portal, and focussing on RBAC-based grants in the new portal instead. (They’re more finely grained, to a specific resource, resource group, or set of actions.)

Because an Azure Directory is not a resource, and does not live in the subscription, the co-owner concept does not apply to it.

“User administrator” and “Global administrator” are security roles applied at the Azure Directory level. They relate only to the directory, and not any linked subscriptions.

VSTS Accounts are another stand-alone entity.

A VSTS Account can be linked to an Azure Subscription, so that charges can flow to the Azure subscription. If it is not linked, then there’s no way to use any paid services (as VSTS doesn’t have its own commerce system).

A VSTS Account can be linked to an Azure Directory. This is essentially like “domain joining” a PC; it opts you into a number of management advantages. If it is not linked, then you can only use Microsoft Accounts for sign-in, and it essentially maintains its own lightweight identity store in lieu of the directory.

All Azure Subscriptions are part of an Azure Account. This is where the billing information is maintained.

All Azure Accounts have a Service Administrator and an Account Owner. These are security roles applied at the Account level. They do not grant any rights into the subscriptions, directories, or VSTS accounts (as they are all different, independent entities).

When you login to https://portal.azure.com, you login with an identity that’s in the context of a directory. You can see your current directory context top-right. You will see the different resources which are within subscriptions that are linked to your current directory. You may have no subscriptions at all, in which case you just see the directory but an otherwise empty portal.

When you login to https://manage.windowsazure.com, you must always be in the context of a subscription. (Old portal, old rules.) You will see all of the directories that you have access to as a user, regardless of which subscription context you’re in. Even if you have access to a directory, but you are just lacking a subscription, they will boot you out of the portal with an error about having no subscriptions. To work around this, we grant everybody at Readify co-admin access to an “Authentication Helper” subscription. It’s empty, but it lets you login with your OrgId and then swap to the other directory that you were actually looking for. I really dislike the old portal.

What it solves

Imagine you’re building an e-commerce site on Azure.

You need to generate order numbers, and they absolutely must be unique.

A few options come to mind initially:

Let SQL Azure generate the numbers for you. The downside to this approach is that you’re now serializing all of your writes down to a single thread, and throwing away all of the possible benefits from something like a queuing architecture. (Sidenote: on my current project we’re using a NoSQL graph DB with eventual consistency between nodes, so this wouldn’t work for us anyway.)

Use a GUID. These are far from human friendly. Seriously, can you imagine seeing an order form with a GUID on the top?

Prefix numbers with some form of machine specific identifier. This now requires some way to uniquely identify each node, which isn’t very cloud-like.

As you can see, this gets complex quickly.

SnowMaker is here to help.

What it does

SnowMaker generates unique ids for you in a highly distributed and highly performant way.

Ids are guaranteed to be unique, even if your web/worker role crashes.

How to use it

The only caveat not shown here is that you need to take responsibility for the lifecycle of the generator. You should only have one instance of the generator per app domain. This can easily be done via an IoC container or a basic singleton. (Multiple instances still won’t generate duplicates, you’ll just see wasted ids and reduced performance.) Don’t create a new instance every time you want an id.

Other interesting tidbits

The name is inspired by Twitter’s id generator, snowflake. (Theirs is more scalable because it is completely distributed, but in doing so it requires node-specific configuration.)

Typical id generation doesn’t even use any locks, let alone off-box communication. It will only lock and talk to blob storage when the id pool has been exhausted. You can control how often this happens by tweaking the batch size (a property on the generator). For example, if you are generating 200 order ids per server per second, set the batch size to 2000 and it’ll only lock every 10 seconds.

Node synchronisation is done via Azure blob storage. Other than that, it can run anywhere. You could quite easily use this library from AppHarbor or on premise hosting too, you’d just wear the cost of slightly higher latency when acquiring new ids batches.

The data persistence is swappable. Feel free to build your own against S3, Ninefold Storage, or any other blob storage API you can dream up.

Under the covers

SnowMaker allocates batches of ids to each running instance. Azure Blob Storage is used to coordinate these batches. It’s particularly good for this because it has optimistic concurrency checks supported via standard HTTP headers. At a persistence level, we just create a small text file for each id scope. (eg, the contents of /unique-ids/some-id-scope would just be “4”.)

One issue worth noting is that not all ids will always be used. Once a batch is checked out, none of the ids in it can ever be reallocated by SnowMaker. If a batch is checked out, only one id is used, then the process terminates, the remaining ids in that batch will be lost forever.

Here’s a sequence diagram for one client:

Here’s a more complex sequence diagram that shows two clients interacting with the store, each using a different batch size: