Console Login

Serverless on Metal: Building High-Performance FaaS Architectures Without Vendor Lock-in

Serverless on Metal: Building High-Performance FaaS Architectures Without Vendor Lock-in

Let’s cut through the marketing noise immediately. "Serverless" is a lie. There are always servers. The only difference is whether you control the kernel, the latency, and the bill, or if you hand that control over to a giant conglomerate in exchange for unpredictable "cold starts" and an opaque pricing model.

I’ve spent the last six months migrating a high-traffic logistics platform away from a purely AWS Lambda-based architecture. Why? Because when you are calculating shipping routes across the Nordics, a 500ms cold start latency on an API Gateway is unacceptable. Furthermore, with the GDPR enforcement that kicked in this May, relying on US-based cloud providers under the shaky Privacy Shield framework is keeping our legal team awake at night.

The solution isn't to abandon the event-driven convenience of Functions-as-a-Service (FaaS). The solution is to own the stack. Here is how we build pragmatic, high-performance serverless architectures on pure KVM virtual machines, right here in Norway.

The "Lambda Tax" and the Case for Self-Hosted FaaS

In 2018, the narrative is that you should decompose everything into functions. But if you have ever run a high-throughput system on public cloud functions, you know the pain points:

  • Cold Starts: The container spin-up time can kill user experience.
  • Vendor Lock-in: try moving an AWS Lambda Node.js function to Azure Functions without rewriting your triggers. Good luck.
  • Cost Spikes: API Gateway requests are often more expensive than the compute itself.

By deploying a framework like OpenFaaS on top of a robust VPS, we get the developer velocity of serverless with the raw I/O performance of dedicated hardware. We keep the data inside Norwegian borders, satisfying Datatilsynet, and we stop paying per-invocation premiums.

Architecture Pattern: The Hybrid KVM Cluster

We are not abandoning containers; we are orchestrating them intelligently. The most robust pattern we are seeing in production right now involves a small cluster of KVM instances running Docker Swarm or Kubernetes (v1.12), serving as the substrate for OpenFaaS.

Infrastructure Requirements

You cannot run this on cheap, oversold shared hosting. Function containers need to spawn instantly. This requires NVMe storage and zero CPU steal time.

Pro Tip: When provisioning your nodes, always check the underlying disk scheduler. On many VPS providers, it defaults to CFQ. For NVMe-backed virtualization, switch to noop or deadline to reduce latency.
# Check current scheduler
cat /sys/block/sda/queue/scheduler

# Change to noop for lower latency on NVMe (add to /etc/rc.local to persist)
echo noop > /sys/block/sda/queue/scheduler

At CoolVDS, our standard KVM templates are tuned for this out of the box, which is why we see disk write speeds consistently topping 1GB/s, essential for rapid container hydration.

Implementation: Deploying OpenFaaS on Ubuntu 18.04

Let's look at a real configuration. We will use Docker Swarm for simplicity, as it requires less overhead than Kubernetes for small-to-medium clusters.

First, initialize the Swarm on your primary CoolVDS node:

docker swarm init --advertise-addr $(hostname -i)

Next, we clone the OpenFaaS repository and deploy the stack. Note that we are pinning the version to ensure stability.

git clone https://github.com/openfaas/faas
cd faas
./deploy_stack.sh

Once deployed, your gateway is exposed. However, the default Nginx configuration in many container setups is too permissive for production. You need to tighten the timeouts and buffer sizes to handle heavy payloads without 504 Gateway Timeouts.

Here is a snippet of the Nginx configuration we inject into the gateway service:

http {
    # ... standard config

    # Optimize for high concurrency
    keepalive_timeout 65;
    keepalive_requests 100000;
    
    # Buffer size handling for larger payloads (images/json)
    client_body_buffer_size 128k;
    client_max_body_size 50M;

    # Upstream configuration to the provider
    upstream functions {
        server 127.0.0.1:8080;
        keepalive 16;
    }
}

The "Async-Worker" Pattern

The most effective pattern for 2018 isn't replacing your whole API with functions. It's the Async-Worker Pattern. Keep your monolithic Laravel or Django app for the main CRUD operations. It's fast, cacheable, and simple.

Use the FaaS cluster for the heavy lifting:

  1. User uploads a high-res image to your app.
  2. App saves to object storage (Minio hosted on CoolVDS or S3).
  3. App fires an asynchronous web hook to the OpenFaaS gateway.
  4. FaaS function (Python/ImageMagick) wakes up, processes the image, and pushes the thumbnail back.

This keeps your user-facing application snappy. If the image processing queue gets backed up, it doesn't degrade the web server performance because they are isolated on different process groups or even different CoolVDS instances.

Code Example: Python Image Resizer

Here is the handler.py for a simple resizing function using Pillow. Notice we aren't including heavy libraries in the function code itself if we can help it, keeping the cold start fast.

from PIL import Image
import io
import os

def handle(req):
    """handle a request to the function
    Args:
        req (str): request body
    """
    try:
        # Assuming req contains bytes of the image
        image_data = io.BytesIO(req.encode('latin1')) 
        img = Image.open(image_data)
        
        # Resize logic
        img.thumbnail((128, 128))
        
        out_buffer = io.BytesIO()
        img.save(out_buffer, format="JPEG")
        
        return out_buffer.getvalue()
    except Exception as e:
        return str(e)

Optimizing for Norwegian Network Topology

Latency is physics. If your customers are in Oslo, Bergen, or Trondheim, routing traffic through a data center in Frankfurt or Dublin adds unnecessary milliseconds.

By hosting your FaaS gateway on a CoolVDS instance in Norway, you are peering directly at NIX (Norwegian Internet Exchange). We typically see ping times under 5ms to major Norwegian ISPs. For financial trading bots or real-time bidding systems—common use cases for serverless architectures—this advantage is mathematically significant.

Security Considerations in the Post-GDPR Era

Since May 25th, the rules have changed. Data Controllers are liable for their processors. When you run your own FaaS stack:

Feature Public Cloud FaaS Self-Hosted (CoolVDS)
Data Location Opaque (Region based) Guaranteed Norway
Runtime Security Shared Kernel (mostly) Isolated KVM Kernel
Log Retention Provider Default Fully Configurable

We recommend enabling Docker Content Trust (DCT) to ensure only signed function images are deployed to your swarm.

export DOCKER_CONTENT_TRUST=1
docker stack deploy func_stack -c docker-compose.yml

Conclusion

Serverless is a powerful architectural pattern, but it shouldn't imply "loss of control." By combining the agility of OpenFaaS with the raw, consistent performance of CoolVDS NVMe instances, you build a system that is faster, cheaper at scale, and legally safer than public cloud alternatives.

Stop paying the latency tax. Spin up a CoolVDS KVM instance today and deploy your first function in under 60 seconds. Your response times (and your CFO) will thank you.