Where your Azure spend actually goes
Cloud bills rarely grow because of one bad decision. They grow because dozens of small, individually reasonable choices accumulate, and because nothing in the platform makes waste visible until someone deliberately looks for it. The useful news is that cloud waste is unusually concentrated: in most environments a handful of line items account for the majority of the savings available, and finding them takes an afternoon rather than a consulting engagement. Here is where we would look, roughly in the order that pays best.
First, make the bill readable
Before changing anything, you need to be able to attribute cost to something meaningful. A bill organised by resource type tells you that you spend heavily on compute, which you already knew. A bill organised by application, environment and team tells you where to act. That means tags, applied consistently, on everything. At minimum: environment, application and owner. Azure Policy can require them at creation time, which is far more effective than periodic tidying, because the resources that escape tagging are exactly the ad-hoc ones that turn into waste. Then set up cost analysis grouped by those tags, and a budget alert per environment rather than one for the whole subscription. A single subscription-level alert tells you that something grew. A per-environment alert tells you which thing grew, which is the difference between a useful notification and background noise. This step produces no savings on its own, and skipping it is why most cost-reduction efforts stall after the obvious wins.
Non-production environments are usually the largest single win
In most organisations, development, test and staging environments are provisioned like production and used like a laptop: heavily for eight hours on weekdays, and not at all the rest of the time. Running them continuously means paying for roughly three times the hours you use. Shutting them down outside working hours is the highest-return change available in a typical environment, it carries essentially no risk, and it can be automated with a schedule rather than requiring anyone to remember. The related pattern is environments that outlived their purpose. Almost every long-running subscription contains a test environment built for a migration that finished, a proof of concept nobody formally closed, and a duplicate staging environment created during an incident. These cost full price indefinitely. Sorting resources by creation date and asking who owns anything untouched for ninety days will usually find several. While you are there, look for orphans specifically: disks whose virtual machine was deleted, public IP addresses no longer attached to anything, and load balancers with no backend. These are pure waste, they are invisible in normal use, and they are easy to enumerate.
Databases are where over-provisioning hides
Compute over-provisioning is widely understood and reasonably well managed, because virtual machine sizing is a familiar conversation. Database over-provisioning is neither, and it is often the larger number. Managed database tiers are usually chosen early, during a period when nobody knows what the load will be, and then never revisited. Check actual utilisation over a representative month rather than a week, because month-end processing is often what the tier was sized for. If peak usage sits far below the provisioned tier, you are paying for headroom you do not use. For workloads with genuinely intermittent activity, serverless and elastic options can cost dramatically less than a fixed tier, because they scale down when idle. For workloads with predictable steady load, the opposite is true and a fixed tier with a commitment is cheaper. The mistake is not choosing wrongly, it is choosing once and never checking. Also look at what your backup and retention settings actually cost. Long retention periods on large databases are quietly expensive, and the configured retention is frequently far longer than any policy requires, simply because a longer number felt safer at setup time.
Storage tiers and data movement
Storage is cheap enough that it rarely attracts attention, which is precisely why it accumulates. Most organisations keep everything in the hot tier indefinitely. Lifecycle management rules that move blobs to cool or archive tiers after a defined period are configured once and then reduce cost permanently, with no ongoing effort. The saving per gigabyte is substantial, and for anything holding logs, exports or historical documents the volume is large enough to matter. Data transfer is the line item that surprises people, because it is not something you provision and therefore not something you think about. Moving data out of a region, or out of Azure entirely, is charged. An architecture that keeps chatty components in the same region costs less than an equivalent one spread across regions for reasons that seemed sensible at design time. This is worth checking specifically if you have services in different regions talking to each other frequently. Log retention deserves the same scrutiny. Verbose logging into a managed analytics workspace with a long retention period is a genuinely large recurring cost in some environments, and much of what is retained is never queried after the first week.
Commitments, and making the savings stick
Once you have removed waste, commit to what remains. Reserved capacity and savings plans reduce the rate you pay on steady-state workloads substantially in exchange for a one or three year commitment. The sequencing matters. Committing before you have right-sized means locking in a commitment to resources you were about to shrink, which is a common and expensive mistake. Clean up first, then commit to the floor you are confident you will still be running in a year, and leave the variable portion on demand. The harder problem is that savings decay. Six months after a successful optimisation, most environments have drifted back, because nothing structural changed. What prevents that is unglamorous: tagging enforced by policy, budget alerts per environment, a required owner on every resource, and a standing review often enough that drift is caught while it is small. A quarterly hour spent on the cost analysis view holds most of the gain. One caution on tooling. Automated recommendations are useful for finding candidates and poor at understanding intent. They cannot tell that an apparently idle machine runs a critical monthly job. Treat them as a list to investigate rather than a list to action.
Key takeaway
The pattern in almost every environment is the same. Tag properly so the bill can be read, switch off non-production outside working hours, delete what nobody owns, revisit database tiers against real utilisation, apply lifecycle rules to storage, and only then commit to the remainder. None of it is technically difficult and none of it requires compromising performance, because you are removing capacity that is not being used rather than capacity that is. The part that takes discipline is not the initial cleanup but keeping it clean, and that is a governance habit rather than an engineering one.