Serverless Metabase BI Saved Big Bucks
Switching from Kubernetes to serverless container reduced my cost to zero
Over the last few years, I’ve really enjoyed learning new tech, especially in the open-source space, so when I needed to host a business intelligence (BI) platform in the cloud I thought it would be a great opportunity to learn. But learning can be expensive!
My first choice for a BI platform was one I had a bit of experience with - Microsoft Power BI. However, the Power BI licensing model did not suit my needs (or my wallet), so I looked for open-source solutions. After trying a few I settled on Apache Superset because I was quite impressed and delighted with the capabilities of Superset.
Deploying Superset on Kubernetes
During testing, I had been running Superset on my local machine via Docker, but since my goal was to share the data with others across the internet, I needed to host Superset online. Since I planned on supporting multiple groups, I wanted a way to “stamp out” new instances of Superset for each group but I didn’t want to incur the cost for separate VMs, so I felt continuing to run Superset in a container (actually, 6-8 containers if I recall correctly) would be best. And finally, because I also wanted to learn Kubernetes, I chose Azure Kubernetes Services (AKS) as the platform to host my Superset containers.
Superset has some good documentation for deploying to Kubernetes, so I just needed to figure out how to marry that with AKS. I could write at least a couple of articles on my experience learning to work with AKS and getting Superset deployed (and perhaps I will) but suffice it to say it more than satisfied my desire to learn.
Along the way I found a tool to help me deploy and manage my AKS cluster called Plural. If you really need Kubernetes, but don’t have the time to become an expert, I highly recommend taking a look.
After a few weeks, working just a couple of hours each day, I had the whole thing online and I was quite pleased… until I considered what it was costing me. My first two days cost me an average of US $15 each, which would cost over $450 for the month! Yikes! I had to do something and quick!
Optimizing cost for Azure Kubernetes
I knew I couldn’t handle $450 per month for a solution I had no plans to charge for, so I immediately stopped building and started looking for ways to optimize. Nearly all of the cost was due to the number of compute nodes in my AKS cluster, so the obvious way was to reduce cost was to reduce nodes.
I started by letting the AKS cluster auto-scale and as a result it was sometimes running as many as 5 nodes. That’s great for resiliency, availability and performance, but I was the only user of the site, I was only using it a couple of hours a day, and I wasn’t concerned about 5 9’s of availability.
Looking into my options (below), I found that I could set the Scale method for the cluster to Manual, and I could enforce Min and Max values.
I started with Min: 1 and Max: 3, but found it was constantly running with 3 nodes because AKS wants to be resilient, and 3 nodes was still going to cost me $300 per month. Then I switched to 2 nodes for a couple of days and things were running fine, but I still didn’t want to pay $200 per month so I reduced it to just 1 node. Here is what my daily costs looked like as I made these changes.
You can see in the chart that around May 22nd the daily cost jumped up. I didn’t notice this until over a week later and found that my manual scaling to a single node had changed and I had been running with 2 expensive nodes for several days. After some hurried investigation I realized that the way I had my helm chart configured, when I did a deployment, it would override the manual scale settings I had configured in the Azure portal. I figured that out and was able to stick to just 1 node. At least until I realized that it was crazy to spend over $100 per month for something that was being used just a couple of hours a day.
Enter Azure Container Apps and Metabase
Around that time, I had been learning about Azure Container Apps which promised easier management and potentially lower cost. My first thought was to re-deploy Superset to Container Apps, but there wasn’t an easy way to deploy and manage a multi-container application like Superset on Container Apps at that time. (That has changed now, if interested check out Thorston Hans’ post.)
At this time, I was very keen on reducing my costs, and I was realizing that Superset might not be the best solution for the non-tech folks who were the intended audience of my solution. I went looking for options and found Metabase, which is quite easy to use and runs in a single Docker container. I did some testing and quickly figured out I could run Metabase on Azure Container Apps, pointed to the same PostgreSQL database. I also figured out that instead of $4 per day for running AKS, Container Apps would only cost $1 per day per instance of Metabase! Woohoo!
But wait, there’s more!
I know this post is long, but there are 2 more important pieces of the puzzle.
Tightening the belt
I was paying $1 per day per instance of Metabase (per Container App), but I was allocating 2 CPU cores and 4 GB of memory per container. Would Metabase run on less?
Absolutely! I reduced the CPU cores to 1 and memory to 2 GB and Metabase has been running just fine.
Research pays off
I decided to check out the Azure Pricing Calculator to see if I could squeeze a bit more efficiency out of my Container Apps solution that was already saving me a ton of money. One word caught my attention - FREE!
The page can be a bit confusing and I’m not going to try to explain it here, but I realized that while Container Apps runs on a “consumption” model, I was “consuming” a lot of vCPU and Memory because my Container Apps were running 24x7. I also saw that the first 2 million requests, 180,000 vCPU-seconds and 360,000 GiB-seconds each month are free.
So, the question became how can I reduce my consumption to as close to those free numbers as possible? It turns out the answer is easy, but there is a catch.
Serverless nirvana
Just as AKS had the ability to scale the number of nodes, so does Container Apps. For Container Apps the term is “replicas”, and it means how many instances of your container can run at a given time. My Min/max replicas was set to 1 but changing it to 0 meant I was now running “serverless”.
I’ll show you what this is costing me now, but before I do your own users/customers must be the patient type. You see when the replicas setting is set to 0, your Container App will be shut down after a period of inactivity. Then, when a new request comes in it has to start up again, and at least in the case of Metabase this startup is not instant - it takes 15-30 seconds.
For me, this means when I’m done working on this project for the day the Container Apps I have deployed shut down and don’t start again until I or someone else visits the site. When I do visit the site to do some data analysis again it takes a few seconds for the site to start up, but as long as I continue to use it the site keeps running and performance is great.
What’s it costing me now?
After all this work I am quite pleased with the results. With 3 instances of Metabase deployed, though I generally do most of my work in just one of them, Metabase on Container Apps has cost me $0.
Apparently, my consumption is so low that I am not exceeding the monthly free resources. This is amazing! From a $180 per month down to nothing! This means I can focus all of my time now on building a better solution and doing some data analysis instead of trying to save money… there’s still that pesky database cost… hmmm.
Full disclosure - I do work for Microsoft, but the project I’m working on with Metabase is a personal one and has nothing to do with Microsoft. Also, this Substack is not reviewed or edited by anyone at Microsoft, and everything said here is my own personal opinion.
Hi Chris. I came across your article on deploying Metabase with Azure Container Apps.
I tried it and it worked for a while. I am really grateful.
But now it's been shutting down while I'm working and spinning up way too many replicas.
This is the most common error I keep having:
"Msg":"Probe with executor TcpExecutor failed with status code: 1","Reason":"ProbeFailed","EventSource":"ContainerAppController"
I'm hoping you could help me. I haven't found any other resource on launching Metabase using Azure Container App.