fnproject/fn
The container native, cloud agnostic serverless platform.
Healthy across the board
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 4w ago
- ✓22+ active contributors
- ✓Distributed ownership (top contributor 49% of recent commits)
Show all 6 evidence items →Show less
- ✓Apache-2.0 licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/fnproject/fn)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/fnproject/fn on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: fnproject/fn
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/fnproject/fn shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 4w ago
- 22+ active contributors
- Distributed ownership (top contributor 49% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live fnproject/fn
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/fnproject/fn.
What it runs against: a local clone of fnproject/fn — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in fnproject/fn | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 60 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of fnproject/fn. If you don't
# have one yet, run these first:
#
# git clone https://github.com/fnproject/fn.git
# cd fn
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of fnproject/fn and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "fnproject/fn(\\.git)?\\b" \\
&& ok "origin remote is fnproject/fn" \\
|| miss "origin remote is not fnproject/fn (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "api/agent/agent.go" \\
&& ok "api/agent/agent.go" \\
|| miss "missing critical file: api/agent/agent.go"
test -f "api/agent/drivers/docker/docker.go" \\
&& ok "api/agent/drivers/docker/docker.go" \\
|| miss "missing critical file: api/agent/drivers/docker/docker.go"
test -f "api/datastore/datastore.go" \\
&& ok "api/datastore/datastore.go" \\
|| miss "missing critical file: api/datastore/datastore.go"
test -f "api/agent/grpc/runner.proto" \\
&& ok "api/agent/grpc/runner.proto" \\
|| miss "missing critical file: api/agent/grpc/runner.proto"
test -f "api/common/errors.go" \\
&& ok "api/common/errors.go" \\
|| miss "missing critical file: api/common/errors.go"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 60 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~30d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/fnproject/fn"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Fn is an open-source, event-driven Functions-as-a-Service (FaaS) platform written in Go that executes arbitrary Docker containers as serverless functions. It abstracts away infrastructure management while supporting any language via containerization, allowing developers to deploy functions to public clouds, private data centers, or hybrid environments with a unified API and CLI. Monolithic server with clear layering: api/agent/ contains the core function execution engine; api/agent/drivers/ abstracts container runtimes (currently Docker via docker.go); api/agent/grpc/ handles distributed function execution via protobuf (runner.proto). The agent manages container pools, image caching, networking, and call lifecycle through a data_access.go abstraction layer.
👥Who it's for
DevOps engineers and platform teams building internal serverless infrastructure, and developers who want to run Lambda-compatible functions on-premises or in multi-cloud setups without vendor lock-in. Contributors are typically Go engineers familiar with container orchestration and gRPC.
🌱Maturity & risk
Actively developed and production-ready. The codebase is 991KB of Go with comprehensive test coverage (agent_test.go, docker_test.go, pool_test.go files present), full CircleCI CI/CD pipeline configured, and recent activity visible in the file structure. However, it's not as widely adopted as AWS Lambda or OpenFaaS.
Moderate risk: depends heavily on Docker daemon stability and image registry availability (registry.go, image_puller.go are critical paths). The architecture requires careful management of container pools (docker_pool.go) and eviction policies (evictor.go) to avoid resource exhaustion. Single point of failure if the agent process crashes, though clustering is supported via the gRPC hybrid client.
Active areas of work
Based on the file structure, active development focuses on Docker driver optimization (docker_pool.go, image_cache.go, image_cleaner_test.go suggest ongoing pooling and cleanup work), gRPC-based hybrid execution (api/agent/hybrid/), and resource management (evictor.go for container eviction). The CircleCI pipeline indicates continuous testing infrastructure.
🚀Get running
Clone the repo, ensure Docker 17.10+ is running, then build with make build. Start the Fn server with fn start (requires the CLI installed via curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh). Deploy a function using fn deploy --all in a function directory with func.yaml.
Daily commands:
Single-node: fn start (requires Docker daemon running and Fn CLI installed). Multi-node: deploy container image from the included Dockerfile, configure via environment variables (see api/agent/config.go for config options). Tests run via make test or CircleCI pipeline.
🗺️Map of the codebase
api/agent/agent.go— Core agent orchestration logic that manages function execution, container lifecycle, and resource allocation—entry point for all serverless workloads.api/agent/drivers/docker/docker.go— Docker driver implementation for container execution; essential for understanding how Fn isolates and runs functions in containers.api/datastore/datastore.go— Datastore abstraction layer defining interfaces for persisting functions, routes, apps, and call history—all state is routed through this.api/agent/grpc/runner.proto— gRPC service definition for function execution protocol; defines the contract between agent and runner components.api/common/errors.go— Centralized error types and handling for the platform; understanding error semantics is critical for debugging and API responses.api/agent/slots.go— Slot/concurrency management system that controls function execution parallelism and resource multiplexing across containers.Dockerfile— Defines how the Fn server itself is containerized; essential for deployment and understanding build artifacts.
🛠️How to make changes
Add a New Container Driver
- Define the driver interface implementation in a new file
api/agent/drivers/[drivername]/[drivername].goimplementing thedrivers.Driverinterface fromapi/agent/drivers/driver.go(api/agent/drivers/driver.go) - Implement required methods:
CreateContainer(),Run(),GetStats(),Logs(),RemoveContainer(),Freeze(),Unfreeze(),InspectContainer()to wrap your container platform API (api/agent/drivers/[drivername]/[drivername].go) - Register your driver in the init function of
api/agent/drivers/register.goby adding an entry mapping a name to your driver factory (api/agent/drivers/register.go) - Update
api/agent/config.goto parse driver-specific config flags (e.g.,DOCKER_SOCK_ADDR) and pass them to the driver constructor (api/agent/config.go) - Add unit tests following the pattern in
api/agent/drivers/driver_test.goto validate container lifecycle operations (api/agent/drivers/driver_test.go)
Add a New Datastore Backend
- Create a new package
api/datastore/[backend]/and implement thedatastore.Datastoreinterface fromapi/datastore/datastore.go(api/datastore/datastore.go) - Implement CRUD methods:
InsertApp(),GetApp(),UpdateApp(),InsertRoute(),GetRoute(),InsertCall(),GetCall()etc. to delegate to your backend storage system (api/datastore/[backend]/datastore.go) - For SQL-based backends, use the migration system in
api/datastore/sql/migratex/migrate.goto define schema migrations; place migration files inapi/datastore/sql/migrations/(api/datastore/sql/migratex/migrate.go) - Update the datastore factory in
api/agent/data_access.goto instantiate your backend based on config (e.g., environment variableDB_URL) (api/agent/data_access.go) - Add comprehensive tests using the standard test harness in
api/datastore/datastoretest/test.goto validate all CRUD and query operations (api/datastore/datastoretest/test.go)
Add Function Execution Logging
- Create a new logger in
api/agent/func_logger.go(or extend it) that implements the logging interface to capture function stdout/stderr (api/agent/func_logger.go) - In
api/agent/call.go, attach the logger when preparing theCallexecution context so output is streamed during execution (api/agent/call.go) - Update the driver's
Run()method contract inapi/agent/drivers/driver.goto accept and use the logger for capturing container logs (api/agent/drivers/docker/docker.go) - Persist logs to the datastore by inserting a call log record in the datastore after execution completes in
api/agent/agent.go's call handling flow (api/agent/agent.go)
Add a New Resource Metric (CPU, Memory, Latency)
- Define a new field in the
Callstruct inapi/agent/call.goor extend the stats model inapi/agent/drivers/stats/stats.go(api/agent/drivers/stats/stats.go) - Update the driver's
GetStats()method inapi/agent/drivers/driver.goto collect the new metric from the container platform (api/agent/drivers/docker/docker.go) - Store the metric in the datastore by extending the Call or CallLog schema in
api/datastore/datastore.goand adding a migration inapi/datastore/sql/migrations/(api/datastore/datastore.go) - Expose the metric in any API responses by updating serialization in the relevant API handler (typically in a
api/server/orapi/routes/package if present) (api/agent/agent.go)
🪤Traps & gotchas
Docker daemon must be running and reachable (Unix socket or TCP configured via DOCKER_HOST env var). Image pulling requires registry credentials in docker login or mounted config.json. The agent expects writable /tmp for container logs and metadata. Container pool sizes and eviction timeouts (configured in config.go) must be tuned for workload; defaults may cause OOM on small systems. gRPC hybrid mode requires explicit cluster configuration; standalone mode works out-of-box.
🏗️Architecture
💡Concepts to learn
- Container pooling and warm starts — Fn's performance advantage over cold-start Lambda relies on reusing containers via docker_pool.go; understanding pool lifecycle (acquire/release/evict) is essential to performance tuning
- gRPC and Protocol Buffers — Fn uses gRPC (runner.proto) for distributed function execution and hybrid clustering; essential for understanding multi-node deployments
- Docker image layer caching and registry interactions — image_cache.go and image_puller.go optimize function startup by caching layers and managing registry auth; critical for high-throughput deployments
- Resource eviction policies (LRU/LFU) — evictor.go implements container lifecycle management to prevent resource exhaustion; understanding eviction strategies (time-based, memory-based) is needed for scaling
- Function-as-a-Service architecture patterns — Fn demonstrates core FaaS patterns: stateless function execution, event-driven invocation, auto-scaling via pooling, and cold-start mitigation
- Docker networking and container isolation — docker_networks.go manages network namespaces and inter-container communication; essential for understanding security boundaries and function-to-function calls
- Goroutines and Go concurrency patterns — Agent extensively uses goroutines for async function execution and container lifecycle management; understanding Go's concurrency model is foundational to reading agent.go
🔗Related repos
fnproject/cli— Official CLI tool that wraps the Fn server API; required for developers to deploy and invoke functionsfnproject/flow— Workflow orchestration engine built on top of Fn for composing multi-step function pipelinesfnproject/ui— Web dashboard for Fn server providing function management, logs, and metrics visualizationfnproject/docs— Official documentation and tutorials; contains operator guides, API specs, and deployment patternsopenfaas/faas— Alternative FaaS platform with similar goals but different architecture (uses Kubernetes, Go function framework); good for understanding design trade-offs
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for api/agent/hybrid/client.go
The hybrid client module handles communication between agents and remote runners, but there are no corresponding test files (*_test.go) for hybrid/client.go. Given the criticality of this component in the agent's architecture (seen in runner_client.go and pure_runner.go), adding tests would improve reliability and prevent regressions when modifying hybrid execution logic.
- [ ] Create api/agent/hybrid/client_test.go with tests for client initialization and connection handling
- [ ] Add tests for error cases in hybrid client communication
- [ ] Verify integration with the nop.go fallback implementation
- [ ] Add benchmarks for hybrid client performance-sensitive operations
Add CI workflow for Docker driver regression testing with multiple Docker versions
The Docker driver (api/agent/drivers/docker/) is critical infrastructure with existing tests, but .circleci/config.yml appears minimal. Add a GitHub Actions or CircleCI workflow that tests against multiple Docker versions (20.x, 21.x, 24.x) to catch compatibility issues early. This is especially important given the docker_pool.go, image_cache.go, and registry.go complexity.
- [ ] Create .github/workflows/docker-driver-test.yml with matrix strategy for Docker versions
- [ ] Configure workflow to run api/agent/drivers/docker/*_test.go suite
- [ ] Add tests for image_puller.go, image_cleaner, and registry.go against each Docker version
- [ ] Set up failure notifications for Docker API compatibility regressions
Add unit tests for api/agent/state_trackers.go and api/agent/resource.go resource management
These files (state_trackers.go and resource.go) manage critical state for container lifecycle and resource allocation, but state_trackers.go has no test file. Resource.go has resource_test.go but appears incomplete. Adding comprehensive tests for state transitions, concurrent access patterns, and edge cases in resource allocation would prevent subtle bugs in the agent's core scheduling logic.
- [ ] Create api/agent/state_trackers_test.go with tests for state transition validity and concurrency
- [ ] Expand api/agent/resource_test.go with additional test cases for edge cases in resource constraints
- [ ] Add tests for resource exhaustion scenarios and cleanup after container eviction
- [ ] Test interaction between state_trackers.go and slots.go (slot allocation lifecycle)
🌿Good first issues
- Add missing integration tests for image_puller.go retry logic with registry failures—currently only basic registry_test.go exists, gaps in timeout/backoff scenarios
- Document the relationship between Call.go request/response flow and agent.go execution engine with ASCII diagrams in api/agent/doc.go—currently undocumented
- Implement metrics/instrumentation stubs in api/agent/drivers/stats/stats.go beyond basic container stats collection to expose function latency percentiles and pool utilization
⭐Top contributors
Click to expand
Top contributors
- @CI — 49 commits
- @skinowski — 10 commits
- @ahjones — 9 commits
- @marvin659 — 3 commits
- @dmutreja — 3 commits
📝Recent commits
Click to expand
Recent commits
3e2893d— Releasing version 0.3.770 (CI)9f6d06f— Releasing version 0.3.769 (CI)a402c5e— Releasing version 0.3.768 (CI)dff902a— Releasing version 0.3.767 (CI)235d44e— fnserver: v0.3.756 release [skip ci] (CI)d7c19fd— update golang version to 1.24.11 (marvin659)8c386dd— fnserver: v0.3.755 release [skip ci] (CI)db92dfd— multi arch build for fnserver (marvin659)273bb32— fnserver: v0.3.754 release [skip ci] (CI)b091933— Fix Unknown permission issue when FDK tried to chmod or bind socket to file and deprecated cgroup v1 mem swappiness api (marvin659)
🔒Security observations
The fnproject/fn codebase has moderate security
- High · Outdated JUnit Dependency —
pom.xml - junit dependency (version 4.12). The pom.xml uses JUnit 4.12 which was released in 2014 and contains known security vulnerabilities. JUnit 4.12 and earlier versions have been superseded by JUnit 4.13.2+ which contain critical security fixes. Fix: Update JUnit to version 4.13.2 or later: <version>4.13.2</version> - Medium · Insecure Maven Repository URL —
pom.xml - repository URL (fn-maven-releases). The repository URL uses HTTP instead of HTTPS for dl.bintray.com. This exposes dependency downloads to man-in-the-middle attacks where malicious packages could be injected during transit. Fix: Update the repository URL to use HTTPS: https://dl.bintray.com/fnproject/fnproject - Medium · CircleCI Token Exposed in README —
README.md - CircleCI badge URL. The README contains a CircleCI badge URL with what appears to be a CircleCI authentication token embedded in the URL (circle-token parameter). This token could be used to gain unauthorized access to the CI/CD pipeline. Fix: Immediately revoke the exposed CircleCI token in the project settings and regenerate it. Remove the token from the README and use environment variables in CircleCI instead. - High · Scratch Base Image with Limited Diagnostics —
Dockerfile - FROM scratch and dind stages. The Dockerfile uses 'scratch' as an intermediate build stage (builder-buildservice), which is appropriate for minimal images. However, the final stage uses 'docker:29-dind' which includes a full Docker daemon. The DinD (Docker-in-Docker) container has elevated privileges and increases the attack surface significantly. Fix: Evaluate if DinD is necessary. If Docker socket mounting is sufficient, use the standard docker client instead of dind. If DinD is required, implement strict resource limits and security policies (seccomp, AppArmor profiles). - Medium · Missing Security Headers in Container —
Dockerfile - EXPOSE 8080 and CMD. The application exposes port 8080 without documented security headers or TLS configuration visible in the Dockerfile. HTTP traffic is unencrypted and vulnerable to eavesdropping. Fix: Implement TLS/HTTPS by adding certificate handling, configure security headers (HSTS, CSP, X-Frame-Options), and consider using a reverse proxy like nginx for enhanced security. - Low · Minimal CVE Scanning in Pipeline —
.circleci/config.yml (not fully shown). No evidence of dependency vulnerability scanning (e.g., OWASP Dependency-Check, Snyk) in the CircleCI configuration visible in the file structure. The codebase should implement automated CVE scanning. Fix: Integrate automated dependency vulnerability scanning tools like: 1) maven-dependency-check-plugin, 2) Snyk, or 3) OWASP Dependency-Check into the CI/CD pipeline. - Medium · No Resource Limits in Docker Configuration —
Dockerfile - CMD and runtime configuration missing. The Dockerfile does not specify memory or CPU limits, which could lead to denial of service if the fnserver consumes excessive resources. The DinD container is particularly resource-intensive. Fix: Document required resource limits in deployment manifests. For Kubernetes/Docker Compose, specify requests and limits. Example: memory: '512Mi', cpu: '500m' - Low · FDK Version Hardcoded Without Update Policy —
pom.xml - fdk.version property. The fnproject FDK version (1.0.52) is hardcoded as a property. Without a defined update and security patch policy, the project may miss critical security updates to dependencies. Fix: Implement a dependency update policy. Use tools like Dependabot or Maven enforcer rules to regularly audit and update dependencies. Pin to patched minor versions (e.g., 1.0.x) rather than exact patch versions.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.