Data software company
One operating picture for an estate split across a data centre and a large Azure footprint.
Management wanted visibility into cloud spend tied to operational metrics. Operations wanted to stop moving between four portals to answer one question. Both needed the same substrate.
The situation
The organisation ran a full Windows stack on an on-premise failover cluster alongside a substantial Azure footprint doing broadly similar work. Two pressures met in the middle: leadership wanted cloud spend explained in terms of operational metrics they already reported against, and the operations team was under standing pressure to consolidate and resize virtual machines without a defensible basis for choosing which.
Both problems had the same root. Billing lived in one place, utilisation telemetry in another, and the inventory that would link either to an owning team or cost centre in a third. Producing one credible right-sizing recommendation meant a week of manual reconciliation, so it happened rarely and was trusted briefly.
What we built
A single operating picture, deliberately scoped so it produced value before it became a platform. The first release did one thing: virtual machine inventory, sizing, disk and processor utilisation, joined to a cost view that mapped Azure billing onto the metrics management actually cared about.
The architecture reflects the environment rather than a house style. This is a Windows-and-Azure organisation, so the design leans into it: Entra ID single sign-on with no local bypass, managed identity for service-to-service authentication, Azure Container Apps for hosting, scheduled container jobs for ingestion, and infrastructure defined as code from the outset. A single PostgreSQL instance carries three workloads through extensions — time-series for metrics and cost rollups, vector storage for document retrieval, and ordinary relational tables for everything else — which kept the moving parts to a minimum for a small team.
Model access sits behind a single abstraction rather than being called directly, because provider portability was a stated requirement: the organisation expected to move inference into its own tenancy for data residency reasons at some later point. That is a configuration change, not a rewrite. We deliberately declined the heavyweight retrieval frameworks in favour of writing the retrieval loop directly — a few hundred readable lines the team can maintain without first learning an abstraction stack.
What changed
The cost conversation became specific. Rather than a total and a growth rate, discussions moved to a named list of workloads with their sustained utilisation, their owner, and what changing them would save. That specificity is what makes the decision possible; the analysis was never the hard part.
Resistance to right-sizing also dropped, for an unglamorous reason. When the utilisation evidence is visible to the application owner as well as to operations, the objection usually evaporates — most pushback is about the absence of shared data rather than disagreement about the plan.
What it was built toward
The roadmap deliberately treated AI as a second phase rather than a launch feature: an assistant grounded in the organisation’s own documentation and meeting records first, with agentic workflows — identify an over-provisioned workload, raise the ticket, track it to completion — sequenced afterwards, once the underlying data was trustworthy enough to act on automatically.
That ordering is the point. An agent that opens tickets against unreliable utilisation data is worse than no agent, because it converts a data quality problem into a stream of work your teams learn to ignore.
The organisation is not identified. Technical detail and figures describe the system as built.
Start with your hardest question.
Tell us the decision your organisation keeps making without good evidence. That is usually the right place to begin.