self-hosted-serverless

module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2026 License: MIT

README

Self-Hosted Serverless

A production-ready, self-hostable alternative to AWS Lambda and Google Cloud Functions. Built with Go, it provides a fast, secure, and independent serverless platform you can run on your own infrastructure.

Overview

Self-Hosted Serverless gives you complete control over your serverless environment:

  • Cloud Independence: No vendor lock-in, runs on any Linux host or container
  • Performance: Go's concurrency model and compiled WASM modules give fast cold starts
  • Security: API key auth, per-IP rate limiting, request size limits, path traversal prevention
  • Observability: Built-in execution metrics, error rates, and cold start tracking

Functions run as Go plugins or WASM modules. A central dispatcher handles HTTP and gRPC requests with timeout enforcement and panic recovery on every execution.

Features

  • HTTP and gRPC: Dual protocol support
  • WebAssembly Runtime: WASI-compatible modules via wazero, compiled module caching
  • Go Plugins: Native Go functions loaded as shared libraries
  • Database Integration: PostgreSQL, SQLite, and Redis
  • Event Bus: Publish and subscribe to events across functions
  • API Key Authentication: X-API-Key header or Authorization: Bearer token
  • Rate Limiting: Per-IP sliding window, configurable via env var
  • Function Timeout: Configurable per-execution deadline with goroutine-level enforcement
  • Panic Recovery: Bad functions cannot crash the server
  • Metrics: Execution count, average duration, error rate, cold start count

Architecture

                        ┌─────────────────────────────┐
                        │         HTTP :8080           │
                        │  CORS, Rate Limit, Auth      │
                        └────────────┬────────────────┘
                                     │
                        ┌────────────▼────────────────┐
                        │        gRPC :9090            │
                        └────────────┬────────────────┘
                                     │
                        ┌────────────▼────────────────┐
                        │      Function Registry       │
                        │  timeout + panic recovery    │
                        └──────┬──────────────┬───────┘
                               │              │
                    ┌──────────▼──┐    ┌──────▼──────┐
                    │ Go Plugin   │    │ WASM (WASI)  │
                    │   (.so)     │    │   (.wasm)    │
                    └─────────────┘    └─────────────┘

Requirements

  • Go 1.24+
  • CGO-capable toolchain (required for go-sqlite3 and the plugin system)
  • Docker (optional)
  • PostgreSQL, Redis (optional)

Quick Start

git clone https://github.com/mstgnz/self-hosted-serverless.git
cd self-hosted-serverless

go mod tidy

# Start without auth (development)
go run cmd/main.go

# Start with auth
API_KEY=secret go run cmd/main.go
Docker
# Single container
docker build -t self-hosted-serverless .
docker run -p 8080:8080 -p 9090:9090 -e API_KEY=secret self-hosted-serverless

# Full stack (Postgres + Redis)
API_KEY=secret POSTGRES_PASSWORD=strongpassword docker compose up -d

Configuration

All configuration is via environment variables.

Variable Default Description
API_KEY (empty) When set, all endpoints (except /health) require this key. Leave empty for development only.
FUNCTION_TIMEOUT_SECS 30 Maximum seconds a single function execution may run
RATE_LIMIT_PER_MIN 100 Maximum requests per IP per minute
POSTGRES_HOST localhost
POSTGRES_PORT 5432
POSTGRES_USER postgres
POSTGRES_PASSWORD postgres
POSTGRES_DB serverless
REDIS_HOST localhost
REDIS_PORT 6379
REDIS_PASSWORD (empty)
SQLITE_DB_PATH data/serverless.db

Authentication

When API_KEY is set, every protected endpoint requires the key. Send it via either header:

curl -H "X-API-Key: secret" http://localhost:8080/functions
# or
curl -H "Authorization: Bearer secret" http://localhost:8080/functions

The /health endpoint is always public.

CLI

# Create a new function scaffold
go run cmd/main.go create function myFunction

# Invoke a function running on the local server
go run cmd/main.go run myFunction

# List registered functions
go run cmd/main.go list

# Show metrics for all functions
go run cmd/main.go metrics

# Show metrics for one function
go run cmd/main.go metrics myFunction

HTTP API

Method Path Description
GET /health Health check (public)
POST /run/{name} Execute a function
GET /functions List all registered functions
POST /events Publish an event
POST /db Execute a SELECT query
GET /metrics Metrics for all functions
GET /metrics/{name} Metrics for one function
Execute a function
curl -X POST http://localhost:8080/run/myFunction \
  -H "X-API-Key: secret" \
  -H "Content-Type: application/json" \
  -d '{"name": "world"}'
Publish an event
curl -X POST http://localhost:8080/events \
  -H "X-API-Key: secret" \
  -H "Content-Type: application/json" \
  -d '{"type": "user.created", "payload": {"id": 42}}'
Query the database

Only SELECT and WITH statements are accepted. Write operations must go through your functions.

curl -X POST http://localhost:8080/db \
  -H "X-API-Key: secret" \
  -H "Content-Type: application/json" \
  -d '{"query": "SELECT id, name FROM users WHERE active = $1", "args": [true]}'

Writing Functions

Go Plugin

Create a function with the CLI, then build it as a shared library:

go run cmd/main.go create function myFunction
cd functions/myFunction
go build -buildmode=plugin -o myFunction.so .

The plugin must export two symbols:

package main

import "github.com/mstgnz/self-hosted-serverless/internal/common"

var Handler = &MyHandler{}

var Info = common.FunctionInfo{
    Name:        "myFunction",
    Description: "Does something useful",
    Runtime:     "go",
}

type MyHandler struct{}

func (h *MyHandler) Execute(input map[string]any) (any, error) {
    return map[string]any{"message": "hello"}, nil
}

Note: Go plugins require CGO and must be compiled with the same Go version and build flags as the server. Linux is the most reliable target.

WebAssembly (WASI)

The runtime uses WASI stdio for I/O. The module receives input as a JSON object on stdin and must write its result as JSON to stdout before exiting with code 0.

Example in Go (compile with GOOS=wasip1 GOARCH=wasm):

package main

import (
    "encoding/json"
    "fmt"
    "os"
)

func main() {
    var input map[string]any
    json.NewDecoder(os.Stdin).Decode(&input)

    result := map[string]any{
        "message": fmt.Sprintf("Hello, %v!", input["name"]),
    }
    json.NewEncoder(os.Stdout).Encode(result)
}
GOOS=wasip1 GOARCH=wasm go build -o functions/hello.wasm .

The server picks up .wasm files automatically from the functions/ directory on startup.

gRPC

Connect to port 9090. The service definition is in proto/function.proto.

# List functions
grpcurl -plaintext localhost:9090 function.FunctionService/ListFunctions

# Execute a function
grpcurl -plaintext -d '{"name": "myFunction", "input": {"key": "value"}}' \
  localhost:9090 function.FunctionService/ExecuteFunction

Examples

See the examples/ directory for runnable examples:

Use Cases

  • API Backends: Lightweight HTTP services without a framework
  • Webhook Processing: Isolated handlers for each integration
  • Data Processing: Batch or stream processing functions
  • ML Inference: Serve models with predictable latency
  • Event-Driven Pipelines: Chain functions via the event bus

Contributing

git clone https://github.com/mstgnz/self-hosted-serverless.git
cd self-hosted-serverless
git checkout -b feature-branch
# make your changes
go test ./...

Roadmap

  • WebAssembly support (WASI stdio I/O)
  • Function metrics and observability
  • API key authentication
  • Per-IP rate limiting
  • Function execution timeout and panic recovery
  • CORS support
  • Docker Compose with health checks
  • Kubernetes manifests
  • Horizontal scaling with a shared function registry
  • Structured JSON logging
  • CLI authentication support

License

MIT

Directories

Path Synopsis
examples
database/redis command
database/sqlite command
grpc/basic command
grpc/client command
http/basic command
functions
hello command
internal
cli
db

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL