Organising and Protecting Azure Resources: Resource Groups, Tags, and Locks
Resource groups, tags, and locks are the everyday organisational layer of Azure governance — the tools you reach for before anything as heavyweight as a policy assignment or a custom RBAC role. Getting these right early makes billing reports readable, access control simpler to reason about, and accidental deletions much rarer.
Resource groups
A resource group's name is worth being deliberate about, since it's often the only context someone gets at a glance. A convention like msftlearn-core-infrastructure-rg packs in what it's for (msftlearn), the kind of resources inside (core-infrastructure), and the resource type itself (rg) — descriptive enough to be useful in a resource list without opening anything.
A resource group has its own location (region), which is where its metadata is stored — the resources inside it can live in different regions from the group itself and from each other. That distinction matters operationally: if the resource group's region has an outage, you can't update anything in the group, because the metadata needed to process that update is unavailable, even though the resources themselves (sitting in other regions) keep running normally in the meantime. Resources aren't confined to talking only within their own group, either — a web app in one resource group can connect to a database sitting in a different one without issue.
A few hard rules apply: resource groups can't be nested and can't be renamed, and every resource belongs to exactly one resource group at a time (though you can add or remove a resource from a group whenever you like, and move it to a different group or subscription — see the resource-moving post in this series for the mechanics and caveats of that).
Beyond the mechanics, resource groups are also where you decide how to organise resources in the first place. A few principles cover most cases:
- Organise for authorisation. Resource groups are a scope for
Azure RBAC, so grouping resources by who needs to administer them simplifies access control — if a database administration team owns everyAzure SQL Databaseinstance, putting them in one group means a single role assignment covers all of them. - Organise for lifecycle. Deleting a resource group deletes everything inside it. That's a genuine advantage for disposable resources — non-production or prototype environments especially — where tearing the whole group down in one action is exactly what you want.
- Organise for billing. Grouping resources by resource group is one of the simplest ways to filter and sort cost reports, making it easier to see where spend is concentrated.
Beyond these three, grouping by resource type (for on-demand services with no single owning app), by department, or by region are all legitimate strategies depending on what the organisation actually needs to see at a glance — and it's worth planning deliberately for how many resource groups you'll end up managing, since that overhead is easy to underestimate. Resource groups are also where access control actually gets implemented day to day: Azure roles, Azure Policy assignments, and resource locks can all be applied at the resource group level, inherited by everything inside.
One resource-group-scoped construct worth knowing: a proximity placement group logically groups resources to minimise latency by keeping them within the same data centre. Proximity placement groups are region-specific and must sit within a single resource group — each one is tied to exactly one.
Resource tags
Tags are metadata — information about a resource, not data held within it — structured as name-value pairs (a user-defined category like Environment paired with a value like Dev). Not every resource type supports tagging, so it's worth checking before relying on one.
Tags earn their keep in a few concrete ways. They let you filter Cost Analysis reports by environment, department, or project. They can be required or enforced through Azure Policy, so resources can't be created without the metadata your organisation needs. They let you retrieve every resource carrying a given tag name or value across resource groups — useful when you need to pull together resources for billing or management purposes that a single resource group can't capture on its own. And they're a common automation trigger: a shutdown:6PM / startup:7AM tag pair on development VMs, for example, is enough for an automation job to shut them down and start them back up on a schedule, cutting cost on resources that don't need to run overnight.
Choosing what to tag with is really a taxonomy decision. Align tags with how the organisation already talks about itself — office locations, confidentiality levels, department names — rather than inventing a parallel vocabulary. Broadly, tagging leans IT-aligned (workload, application, function, environment — useful for reducing the complexity of monitoring assets and making operational decisions) or business-aligned (accounting, ownership, cost responsibility, criticality — useful for understanding the cost and business value of what's deployed), and most organisations end up using a mix of both. Azure Policy is the practical way to keep tagging consistent at scale rather than relying on everyone remembering the convention.
| Tag type | Purpose | Example name-value pairs |
|---|---|---|
| Functional | Categorises a resource by its purpose within a workload — deployed environment, tier, or other operational detail. | app=catalogsearch1, tier=web, env=production |
| Classification | Identifies resource usage or sensitivity. | confidentiality=private, SLA=24hours |
| Accounting | Associates a resource with a group for billing purposes. | department=finance, region=northamerica |
| Partnership | Records the people (beyond IT) associated with or affected by a resource. | owner=jsmith, stakeholders=user1;user2;user3 |
| Purpose | Aligns a resource to a business function to support investment decisions. | businessprocess=support, businessimpact=moderate |
Resource locks
Resource locks protect against accidental changes or deletions by overriding normal user permissions at a given scope — a layer of protection independent of who has what RBAC role. Two lock types exist: a Delete lock (CanNotDelete) prevents deletion but still allows modification, while a Read-only lock (ReadOnly) prevents both deletion and modification, effectively restricting everyone to Reader-level access regardless of their actual role.
Locks can be applied at the subscription, resource group, or individual resource level, and they're cumulative: a lock at a higher scope overrides conflicting settings further down, with the most restrictive lock always winning. Locks can't be applied to management groups at all, and — because locks only apply to control-plane operations, not data-plane ones — a lock on a storage account protects the account resource itself but does nothing to protect the data inside it (blobs, queues, tables, or files can still be deleted or modified through data-plane operations even with a lock in place).
Moving resources interacts with locks in a way that's easy to get backwards: a read-only lock on a resource group blocks resources from being moved into or out of that group. But a read-only lock on the resource itself doesn't prevent that resource from being moved to a different resource group — the lock protects the resource's configuration, not its group membership. Worth checking both the resource's own locks and its resource group's locks before assuming a move will (or won't) go through.