Skip to content
OPEN SOURCE Function → Flow → Gateway, agent-native over MCP

Run your own serverless, end to end.

Compose Functions into Flows and expose them through a Gateway — build, deploy and debug the whole lifecycle yourself, or hand it to a coding agent over MCP. Try it hosted in a minute, or self-host it forever.

Apache 2.0 · Java 25 · Spring Boot · Netty · or run it yourself in one command →

Why FuncHole

A different model from the usual serverless provider.

Most serverless platforms tightly couple deployment, routing, runtime behavior and infrastructure ownership to a single vendor. FuncHole is exploring a different shape — try it hosted, or run every part of it on infrastructure you own.

01

Hosted or self-hosted

Sign in at app.funchole.dev and deploy in a minute, or run the same platform on your own Docker Compose stack — Postgres, NATS, OpenBao and RustFS included.

02

Gateway-first routing

Every request resolves through an explicit Gateway you own — exact paths, :name capture, or a /* wildcard subtree, all under one stable host.

03

Explicit boundaries

Management, ingress, invocation and runtime are separate services with a documented contract between them — not one opaque black box.

04

Two real runtimes

A NODE Function runs your handler; a STATIC Function serves a pre-built site's files directly through the Gateway — no code execution, no cold start.

05

Secrets done properly

Function and Environment secrets are written to OpenBao, never to Postgres in plaintext — injected at invocation time, not baked into an image.

06

Real TLS, not a shim

Self-signed for local dev, real ACME/Let's Encrypt issuance and renewal in production — the same HTTP-01 flow a normal CA-backed site uses.

The model

Function → Flow → Gateway.

Three concepts, composed in order. Everything else — build pipeline, invocation registry, dispatch — exists to make this composition durable and inspectable.

Function

Build once, versioned

Submit source, build to an immutable artifact, deploy to READY. A Function is either NODE (runs your handler) or STATIC (serves a built frontend).

submit → build → READY
Flow

Compose steps

Wire exact FunctionVersions into a step sequence — FUNCTION, RESPONSE, MIDDLEWARE, even a nested SUB_FLOW — then adopt the version.

draft → adopt → ADOPTED
Gateway

Expose under a host

An adopted Flow's path becomes a live route under your Gateway's host — exact, :name, or /* — and the request lifecycle is fully inspectable afterward.

route → invoke → inspect
Architecture

Global coordination is event-driven. Local execution is IPC-driven.

A request resolves through the Gateway, gets frozen as an immutable dependency snapshot in the Invocation Registry, and is coordinated globally over NATS JetStream — while the actual runtime hand-off happens over a fast local IPC channel.

Request lifecycle — one HTTP call, end to end dashed = STATIC bypasses this entire path
completion notification STATIC — served straight from the cached artifact Client HTTP request Gateway resolves Flow Registry + JetStream Dispatcher plans next step Runtime IPC exec
invocation-bound traffic completion / coordination a STATIC Flow never creates an Invocation, and never touches the Registry, NATS or the Dispatcher
Agent-native

Let a coding agent run the whole lifecycle.

The controlplane module runs a real MCP server at /api/mcp. Every operation available over REST — create, build, deploy, wire into a Flow, route, invoke, inspect — is a tool call. An agent authenticates with its own scoped API key, never a user's session.

  • get_flow_full_source returns a Flow's entire dependency tree — every step's Function source inlined, SUB_FLOW steps expanded recursively — in one call.
  • Dedicated fh_mcp_... API keys, separate from user JWTs, scoped for agent access.
  • Build failures return structured detail an agent can act on directly, with example-source tools it can call when it's stuck.
Claude Code opencode Codex CLI Puku
What's implemented

The full lifecycle, end to end — not a demo of one slice.

Create → source → build → deploy → compose → route → invoke → inspect all work through the real product surface, today.

Dual runtime

NODE for handler logic, STATIC for a pre-built frontend — same build pipeline, same deploy lifecycle.

OpenBao-backed secrets

Certificate material and Function/Environment secrets live in OpenBao, injected at invocation time.

Real ACME/Let's Encrypt

HTTP-01 issuance and expiry-based renewal in production; self-signed certs for local dev.

Shared Database / Environment

Attach a Database or Environment profile to a Function or Flow — env vars and secrets resolve at invoke time.

Three route shapes

Exact match, :name path-parameter capture, or a /* wildcard subtree — under one stable gateway host.

Inspectable invocations

Every invocation's immutable dependency snapshot, step results and status are queryable after the fact.

Nested Flows

SUB_FLOW steps expand a referenced Flow's own step sequence in-place — compose Flows out of Flows.

Next.js control-plane UI

Manage Functions, Flows, Gateways and Databases by hand whenever you'd rather not go through an agent.

Built on

No framework magic hiding the moving parts.

Java 25 Spring Boot 4.1 Raw Netty PostgreSQL 17 Flyway NATS + JetStream OpenBao Next.js Docker Compose
Self-host it

One command, full local stack.

Controlplane, Gateway, Postgres, NATS, OpenBao and RustFS all come up together — nothing to provision by hand before your first deploy.

Controlplanelocalhost:7080
Control-plane web UIlocalhost:3000
Gatewayhttps://localhost
NATS monitoringlocalhost:8222
quick-start.sh
$ git clone github.com/<org>/funchole
$ cd funchole
$ docker compose -f docker-compose.dev.yml \
  up --build
 
# verify it's alive
$ curl localhost:7080/actuator/health
→ {"status":"UP"}
 
$
Get started

Own your serverless stack, top to bottom.

Try FuncHole hosted in a minute, or clone it and deploy on infrastructure you control. FuncHole is under active development — tell us where the model breaks.