Console Login

Self-Hosted Serverless: Escaping the Public Cloud Cost Trap in 2025

Self-Hosted Serverless: Escaping the Public Cloud Cost Trap in 2025

Let's get one thing straight: "Serverless" is a lie. There are always servers. The only difference is whether you control them, or whether you pay a premium for Jeff Bezos to control them for you. For years, the industry hype machine screamed that managing your own infrastructure was dead. Yet, here we are in May 2025, and I'm seeing more teams repatriating workloads from AWS Lambda and Azure Functions back to robust VPS setups than ever before.

Why? Two reasons: Cost at scale and Cold Starts.

I recently audited a fintech startup based in Oslo. They were processing transaction webhooks using a public cloud FaaS (Function as a Service) provider. Their bill wasn't linear; it was exponential. Every time a burst of traffic hit the Norwegian banking APIs, their latency spiked because of cold starts—the time it takes for the cloud provider to provision a micro-VM, download the code, and start the runtime. In the world of high-frequency trading or real-time payments, 400ms is an eternity. It's the difference between a successful transaction and a timeout.

The solution isn't to abandon the serverless architecture pattern—it's great for developer velocity. The solution is to own the platform. Today, we are building a self-hosted FaaS platform using OpenFaaS on top of K3s (lightweight Kubernetes), running on CoolVDS NVMe instances. This gives you the developer experience of serverless with the raw I/O performance of a dedicated environment.

The Architecture: Why K3s on VPS?

We choose K3s because standard Kubernetes is too heavy for a lean FaaS setup unless you have a massive cluster. We choose CoolVDS because container spin-up time is almost entirely bound by Disk I/O. When a function scales from 0 to 1, the container image layers must be extracted. If you are on standard SATA SSDs or, god forbid, spinning rust, your functions will lag. CoolVDS provides NVMe storage which effectively eliminates the I/O bottleneck.

Pro Tip: When running Kubernetes on a VPS, always disable swap to ensure stability, but ensure your `vm.overcommit_memory` is tuned correctly. If the kernel kills your kubelet OOM, your cluster dies.

Step 1: Preparing the Base OS

We assume you are running Debian 12 (Bookworm) on a CoolVDS instance located in the Oslo datacenter to keep latency low for Nordic users. First, we need to prep the kernel for container traffic. The standard `sysctl` defaults are too conservative.

cat <

Next, install the necessary dependencies for K3s. We need `curl` and `ca-certificates`.

sudo apt-get update && sudo apt-get install -y curl ca-certificates

Step 2: Installing K3s

We will install K3s without Traefik initially, as we want to configure our own Ingress controller later for finer control over SSL termination and DDoS protection limits. This command sets up the master node.

curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
  --disable traefik \
  --write-kubeconfig-mode 644 \
  --node-name coolvds-node-1" sh -

Verify the node is ready. On a CoolVDS 4 vCPU instance, this usually takes less than 25 seconds.

kubectl get nodes -o wide

Step 3: Deploying OpenFaaS

OpenFaaS is the engine that will manage our functions. We'll use `arkade`, a CLI tool that simplifies installing apps to Kubernetes. It saves hours of wrestling with Helm charts manually.

curl -sLS https://get.arkade.dev | sudo sh

Now, deploy OpenFaaS. Notice how we enable the basic auth plugin immediately for security.

arkade install openfaas \
  --load_balancer=false \
  --set=faasIdler.dryRun=false \
  --set=gateway.directFunctions=true \
  --set=queueWorker.maxInflight=100

This configuration tunes the queue worker to handle higher concurrency, leveraging the underlying CPU power of the VPS.

Step 4: Defining a Function

Let's create a simple function to handle image resizing—a common heavy workload. We define this in a `stack.yml` file. This is where the serverless magic happens. You define the "what", and the cluster handles the "how".

version: 1.0
provider:
  name: openfaas
  gateway: http://127.0.0.1:8080
functions:
  image-resizer:
    lang: python3-debian
    handler: ./image-resizer
    image: registry.gitlab.com/my-org/image-resizer:latest
    labels:
      com.openfaas.scale.min: 1
      com.openfaas.scale.max: 20
    annotations:
      com.openfaas.health.http.path: /_/health
      com.openfaas.health.http.initialDelay: "2s"
    environment:
      output_width: "800"
      output_height: "600"

Setting `com.openfaas.scale.min: 1` is critical here. This prevents the "cold start" problem by keeping one container always warm. On a public cloud, you pay extra for provisioned concurrency. On your own VPS, it costs you nothing but a slice of RAM you're already paying for.

The Performance Reality: NVMe vs The World

When a sudden traffic spike hits—say, a marketing campaign goes live in Oslo—OpenFaaS will attempt to scale from 1 replica to 20. This requires pulling the Docker image and starting containers.
If your VPS has standard SSD storage, this IOPS storm can freeze your database. This is why we standardize on CoolVDS NVMe storage. The high read speeds allow `containerd` to unpack layers instantly without starving other processes.

Metric Public Cloud FaaS Self-Hosted on CoolVDS
Cold Start Latency 200ms - 2000ms < 50ms (Pre-warmed)
Data Sovereignty Varies (US Cloud Act issues) 100% Norway (GDPR Compliant)
Cost Predictability Low (Pay per request) High (Fixed monthly VPS)

Data Privacy: The Norwegian Context

Since the Schrems II ruling and subsequent tightening of Datatilsynet guidelines, sending customer data to US-owned clouds has become a legal minefield. By hosting your FaaS infrastructure on a Norwegian VPS, you ensure that the processing logic and the temporary data storage never leave the jurisdiction. This is not just a technical optimization; it's a compliance necessity for many EU businesses.

Final Configuration: The Gateway

Finally, expose your function gateway securely. Never expose the OpenFaaS gateway directly to the internet without a reverse proxy. Here is a snippet for an Nginx configuration that sits in front of your cluster.

server {
    listen 80;
    server_name functions.example.no;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # DDoS Protection: Rate limiting
        limit_req zone=one burst=20 nodelay;
    }
}

This setup gives you the best of modern development patterns without the downsides of the public cloud. You get the Git-push deployment workflow, auto-scaling, and isolation, but you run it on hardware that screams speed.

Stop paying a "serverless tax" for convenience. If you are serious about latency and data control, build your own platform. Spin up a CoolVDS instance today and take back control of your stack.