← back
project

FP&A Budgeting Engine

Language
Go
Database
SQLite
Architecture
REST API
Infrastructure
Zero deps

A REST API for corporate budget management, actuals ingestion, and variance reporting — built to replace the manual Excel workflow that smaller finance teams still run every month. Single binary, no infrastructure, deploys anywhere.

The problem it solves

At companies below a certain size — typically below 500 employees, or without the budget for enterprise planning platforms like Anaplan or Adaptive Planning — the monthly FP&A close still runs on spreadsheets. Actuals are exported from the ERP, pasted into a workbook, and variances are computed by hand across departments and GL accounts. The process is slow, error-prone, and breaks the moment someone edits the wrong cell.

Large enterprises have solved this with dedicated tooling. The gap is the mid-market: companies that have outgrown Excel but cannot justify a six-figure implementation project. This engine sits in that space — structured schema, versioned budgets, on-demand actuals ingestion, and instant variance reports with no pivot tables and no shared file conflicts.

The goal was not to build something clever.
It was to build something that solves a real problem
finance teams in the mid-market actually have.

Stack

Most finance tooling is Python notebooks or Excel macros — useful for analysis, fragile in production. Go compiles to a single binary with no runtime dependencies, makes every error path explicit, and handles concurrency safely. SQLite was chosen over Postgres deliberately: for a tool running inside a finance team's environment, zero infrastructure matters. The database is a single file. Backups are a file copy.

Layer Choice Reason
Language Go Single binary, no runtime, explicit errors
Routing net/http (stdlib) No deps; method+path routing since Go 1.22
Database SQLite Zero infrastructure, file-based, ships with binary
Schema Auto-migrated CREATE TABLE IF NOT EXISTS on startup

API surface

Three resource groups. Budgets support full CRUD by department, GL account, fiscal period, and version. Actuals are ingested via a single upsert endpoint — idempotent by period, department, and GL code, designed to accept ERP JSON exports directly. Variance endpoints return computed reports immediately.

POST   /api/v1/budgets              Create a budget line
PUT    /api/v1/budgets/{id}          Update amount or notes
DELETE /api/v1/budgets/{id}          Remove a budget line

POST   /api/v1/actuals/ingest        Upsert an actual (idempotent)

GET    /api/v1/variance              Full variance report
GET    /api/v1/variance/alerts       Lines exceeding threshold

GET    /api/v1/health                Returns 200 if DB is reachable

Variance endpoints accept year, period, dept, version, and threshold as query parameters.

Finance concepts implemented correctly

Favourability logic. Whether a variance is good or bad depends on account type. Revenue accounts are favourable when actuals exceed budget; cost accounts when actuals come in under. The engine handles both via a favour_high flag per GL account — a distinction generic reporting tools consistently leave to manual configuration.

Budget versioning. Original budget and up to three forecast revisions are stored separately, enabling a full budget vs. forecast vs. actual three-way comparison without overwriting history — the standard FP&A reforecast workflow.

GL account typing. Accounts are typed as revenue, cogs, opex, capex, or headcount. This drives the P&L rollup structure and the favourability logic together, reflecting how an actual chart of accounts is structured.

Fiscal period decoupling. Periods are stored as integers 1–12, decoupled from calendar months — required for any company not on a January fiscal year.

Example output

Engineering department, FY2024 P09. Cloud infrastructure came in under budget. Consulting exceeded by 51%.

GL Description Budget Actual Var % Status
6100 Salaries & Wages 4,200k 4,380k −4.29% unfavourable
6500 Consulting & Contractors 450k 680k −51.11% unfavourable
5000 Cloud Infrastructure 850k 791k +6.94% favourable

Running it

git clone https://git.samantha42.xyz/samantha/FPandA-Engine
cd FPandA-Engine
cp .env.example .env
go mod tidy
go run ./cmd/server
# → http://localhost:8080
# → fpa.db created on first run

Two environment variables: DB_PATH (use :memory: for tests) and PORT. Demo seed data for Engineering, Sales, and Marketing is included in scripts/seed_demo.sql.


Source at git.samantha42.xyz/samantha/FPandA-Engine