Startseite/ Insights/ Architektur

Mittelstand-Stack, Teil 3: Serverless im eigenen Haus — Funktionen ohne Cloudflare

Architektur 14. Januar 2026 7 min Lesezeit Michael Seliger

In Teil 1 stand Hetzner als bezahlbare, souveräne Basis, in Teil 2 Terraform als Gedächtnis und Versicherung. Jetzt der letzte Baustein: kleine Funktionen — ohne dafür den Stack zu verlassen.

Cloudflare Workers sind technisch hervorragend, daran gibt es nichts zu deuteln. Nur löst „unsere Logik läuft bei einem US-Edge-Anbieter" bei manchen Unternehmen inzwischen Unbehagen aus. Die Frage ist also nicht „ist Cloudflare schlecht" — ist es nicht. Die Frage ist: Bekomme ich eine Funktion genauso einfach hinter eine URL, ohne meinen Stack zu verlassen? Die Antwort ist ja, und sie ist unspektakulär.

Eine Funktion ist nur ein kleiner Container

Entzaubern wir das Wort. Eine „Function" ist im Kern ein kleiner HTTP-Endpunkt, der etwas tut und antwortet. Bei einem Edge-Anbieter ist das hübsch verpackt. Im eigenen Haus ist es ein kleiner Docker-Container neben der App — mehr nicht.

Bei mir sieht das so aus: ein pnpm-Repository, mehrere Funktionen darin, ein Dockerfile. Den Teil, der sonst nervt, übernimmt Dokploy: das kontinuierliche Deployment und Update der Docker-Images — Push, Build, Rollout, Domain davor, Neustart. Genau der Komfort, den man an Workers schätzt — nur auf der Box aus Teil 1, provisioniert wie in Teil 2.

Wer das Worker-Programmiermodell nicht aufgeben will, muss es nicht: Ein schlankes Framework wie Hono läuft auf Cloudflare Workers genauso wie unverändert in einem Node- oder Bun-Container. Man schreibt dieselbe Route — und entscheidet erst beim Deployment, wo sie läuft. Mehr FaaS-Gefühl ginge mit Nitro oder einem selbstgehosteten OpenFaaS; meist ist es das nicht wert.

Beispiel: zwei Funktionen hinter einer URL

Konkret und minimal: ein Endpunkt, der Daten als CSV exportiert, und einer, der nur einen Trigger weiterreicht. Beides in einem kleinen Service, per Docker Compose, von Dokploy im Swarm-Mode ausgerollt.

import { Hono } from 'hono'

const app = new Hono()

// GET /export.csv  -> Daten als CSV ausliefern
app.get('/export.csv', async (c) => {
  const rows = await loadOrders()          // egal woher: DB, API, Datei
  const lines = [['id', 'total', 'created'].join(',')]
  for (const r of rows) lines.push([r.id, r.total, r.created].join(','))
  return c.body(lines.join('\n'), 200, {
    'Content-Type': 'text/csv',
    'Content-Disposition': 'attachment; filename=export.csv',
  })
})

// POST /trigger    -> Event nur weiterreichen
app.post('/trigger', async (c) => {
  const payload = await c.req.json()
  await fetch(process.env.DOWNSTREAM_URL, {
    method: 'POST',
    body: JSON.stringify(payload),
  })
  return c.json({ ok: true })
})

export default app
services:
  functions:
    build: .
    image: registry.example.com/functions:latest
    environment:
      - DOWNSTREAM_URL=https://intern.example.com/webhook
    deploy:
      replicas: 1              # Dokploy: Swarm-Mode
      restart_policy:
        condition: any

Mehr ist es nicht. Ein Repo, ein Dockerfile, ein Compose-Service. Dokploy hängt die Domain davor und hält das Image aktuell. Was an Workers das Schöne war — „Code rein, URL raus" — bleibt. Nur der Betreiber bist du.

Was man gewinnt

  • Kostenkontrolle. Kein Pay-per-Request-Überraschungsei. Das Grundrauschen ist die Box, die ohnehin schon läuft.
  • Keine Cold-Start-Probleme. Der Container läuft. Punkt.
  • Souveränität. Code und Daten bleiben dort, wo der Rest auch liegt — und das ist wieder das Argument, das die ganze Serie trägt.
  • Logs und Debugging an einer Stelle, nicht in einer fremden Konsole.

Und der nüchterne Teil: Es gibt reichlich schwere Serverless-Maschinerie. Oft reicht aber schlicht ein Container mit der nötigen API dahinter. Man muss die große Lösung nicht nehmen, nur weil es sie gibt.

Was man aufgibt

Man gibt das eigentliche Serverless-Versprechen auf: „keine Server". Man zahlt ein Grundrauschen — die Box läuft, ob ein Request kommt oder tausend. Bei einem Lastprofil mit langen Leerlaufphasen kann echtes Pay-per-Request günstiger sein.

Und der Reflex aus Teil 1 gilt hier genauso: Werden die Funktionen weltweit aufgerufen, rauscht man in Latenzprobleme. Ein einzelner Container in Nürnberg ist für Nutzer in Singapur kein Edge-Netz. Wenn globale Low-Latency ein echtes Requirement ist, ist Edge die richtige Wahl — dann ist der Verzicht nicht vertretbar. Für die meisten Mittelstands-Funktionen — interne Tools, Exporte, Webhooks, Trigger — ist er es sehr wohl.

Fazit — der Stack steht

Damit schließt die Serie. Hetzner als bezahlbare, souveräne Basis. Terraform als Gedächtnis und Versicherung. Funktionen als kleine Container im selben Setup. Das Ergebnis: Selbst vielfältigste Systemlandschaften — Website, CMS, Backends, Funktionen, Cron — lassen sich abdecken, ohne den Anbieter zu wechseln. Alles bei einem Hoster, in der EU, in Deutschland.

Wenn Sie genau das wollen — einen modernen Stack, der in der EU bleibt und den ein kleines Team trägt: Der Aufbau, oder das Aufräumen eines gewachsenen, ist Teil meiner Arbeit im Technical Consulting.