I built Goliat: an open-source, self-hosted Azure inventory and FinOps dashboard A developer built and open-sourced Goliat Cloud Inventory, an MIT-licensed, self-hosted Azure inventory and FinOps dashboard that runs read-only inside a user's own tenant. The tool decouples collection from presentation: an Azure Function queries Azure Resource Graph and ARM on a timer, validates a versioned JSON document, and publishes it to Blob Storage, which a Next.js backend imports into PostgreSQL in a single transaction across 73 inventory views. It uses managed identities and least-privilege roles, fails closed on invalid auth configuration, and surfaces missing cost data explicitly rather than reporting zero spend. If you manage more than a couple of Azure subscriptions, you know the drill: the portal is great for one resource at a time, but answering simple questions across everything gets painful. Which VMs are running where? Which resources have no Owner tag? What did we actually spend on AKS last month? I wanted one place to answer those questions, running in my own tenant with read-only access. So I built Goliat Cloud Inventory and released it as open source under the MIT license. What it does - Inventory: 73 views in 12 service groups: compute, containers, web and APIs, networking, storage, databases, security, integration, data and AI, observability, and tags. Each category has an overview with KPIs and charts. Every table supports subscription filters, search, column filters, grouping, sorting, pagination and export. - Global search Ctrl+K / ⌘K over resources, IDs, tags, subscriptions and views, with no extra cloud calls. - FinOps: actual and amortized costs from Azure Cost Management, with daily trends and breakdowns by service, subscription, resource group and resource. Missing data or permissions are shown explicitly, never as zero cost , and currencies are never mixed. - Administration: Function, PostgreSQL and Blob Storage health and metrics, the collector schedule, monitored tag keys, and a warning when the published inventory differs from the imported one. - Roles: sign-in with Microsoft Entra ID, plus an optional Members view to grant or revoke the Goliat admin role, with an audit trail. - Bilingual UI in English and Spanish. How it works Collection and presentation are fully decoupled. They communicate through a single versioned JSON document in Blob Storage. 1. An Azure Function Flex Consumption runs on a timer or on demand. It queries Azure Resource Graph , fills in the gaps from ARM , validates the whole document and publishes it with an ETag condition. If any query fails, nothing is published. 2. The Next.js backend downloads the blob, validates the contract and imports all 73 views into PostgreSQL in a single transaction . A failed import keeps the previous snapshot, and the same ETag is never imported twice. 3. The Refresh button asks the Function for a new generation with an Entra token, waits for it, imports it and reloads the UI. A PostgreSQL advisory lock allows only one manual refresh at a time across all users and replicas. Security by design This was the part I cared about most, since an inventory tool sees everything: - Managed identities everywhere. There are no secrets in the code, and credentials never reach the browser. - Least privilege. The collector only has Reader . The web gets blob read access, Cost Management Reader , and two small custom roles for metrics and Function management. - Configuration only. The collector never reads blob contents, database data, Key Vault secrets, account keys or connection strings. - Fail closed. If the auth configuration is invalid, access is blocked; Goliat never falls back to public mode. Roles are re-checked on the server on every request. - Careful logging. Request bodies, cookies, tokens, query strings and SQL are never logged. Deploying it Everything lives in one resource group, created with Bicep and a PowerShell wrapper: By default this creates App Service F1, PostgreSQL Flexible Server B1ms, a Flex Consumption Function and a Storage account. To be clear: it isn't free , because PostgreSQL doesn't scale to zero. There are stop , start and destroy-plan commands to keep costs under control. Prefer containers? The Dockerfile has runner , collector and migrator targets. To try it locally with fake data, you only need Node.js and PostgreSQL: Stack Next.js 16 · React · shadcn/ui · Tailwind CSS 4 · Recharts · Auth.js · PostgreSQL · Azure Functions Node.js · Bicep · PowerShell · Playwright · GitHub Actions The project has unit tests, PostgreSQL integration tests and Playwright browser tests on desktop and mobile. They run on every push and need no cloud credentials. Try it You don't need an Azure account to look around. The interactive demo https://danieljsaldana.github.io/goliat-cloud-inventory/ runs entirely in your browser with fictional data, including the inventory, FinOps, user management and admin views. If you try it, I'd love to hear what you think. Feedback, issues and stars are all very welcome. ⭐ 👉 https://github.com/danieljsaldana/goliat-cloud-inventory https://github.com/danieljsaldana/goliat-cloud-inventory