Every Azure project eventually has the same conversation.
Where do we store the connection string?
Someone suggests an environment variable, and someone else points out that environment variables end up in deployment pipelines, in Docker compose files, in Terraform state, and occasionally in accidental commits.
A secret manager gets proposed, and the secret manager needs its own credentials to access the secrets.
The problem recurses.
Managed Identity doesn't solve the secret manager problem by adding another layer.
It removes the credential from the equation entirely for workloads running inside Azure, so the application doesn't authenticate with a stored credential but as itself, using an identity that Azure manages automatically.
What Managed Identity actually does When you enable a Managed Identity on an Azure resource, Azure creates an identity in Microsoft Entra ID tied to that resource's lifecycle.
The resource can then request short-lived tokens from the Azure Instance Metadata Service endpoint at , which is only reachable from within Azure infrastructure, and those tokens are what the resource uses to authenticate against other Azure services.
There's nothing to store, nothing to rotate manually, and nothing that can be leaked in a repository because the credential never exists as a static string anywhere in your codebase or configuration.
The key property from Microsoft's documentation is precise: managed identities give code running on an Azure resource access to other resources without developers needing to handle or put credentials directly into code.
The emphasis on "code running on an Azure resource" matters because Managed Identity only works from within Azure.
A local development machine can't reach the Instance Metadata Service endpoint, which means the local development flow still needs an alternative authentication mechanism, typically or a service principal configured for development only.
System-assigned vs user-assigned There are two types of Managed Identity, and Microsoft's current recommendation, updated in its official best practice documentation, is that user-assigned identities are more efficient in a broader range of scenarios.
A system-assigned identity is created directly on a resource and its lifecycle is tied to that resource, so when the resource is deleted, the identity is deleted too.
This sounds convenient but creates a management problem at scale: every resource gets its own identity, every identity needs its own role assignments, and if you have twenty App Services that all need read access to the same storage account, you end up managing twenty separate identities with twenty separate role assignments that have to stay synchronized.
A user-assigned identity is created as a standalone resource in Azure and can be assigned to multiple resources simultaneously, with its lifecycle independent of any particular resource.
If you delete the App Service, the identity persists.
You can pre-define what a user-assigned identity can access, get it approved by whoever owns your access control policy, and then assign it to new resources as they're created without going through a new approval cycle each time.
Microsoft's naming recommendation makes the operational difference clear: name identities after their permission set rather than after the consumer.
An identity named outlives any specific workload and its purpose stays readable in audit logs, while an identity named doesn't communicate what it can do and its permissions tend to drift over time as the team changes.
The security mistake most developers make Turning on Managed Identity and removing the hardcoded credential is the right first step, but stopping there is where most teams leave a significant gap.
Managed identities do not make a workload secure.
They make it credential-free, and that distinction matters because the identity still holds whatever permissions you've granted it, and those permissions are available to anything running on t