How to

How to build a budget vs actuals tracker

Budget owners find out they overspent when finance tells them. Here is the model behind a tracker that shows it as it happens, the prompts to build it, and what it takes to run it.

The short answer

A budget vs actuals tracker is four parts: the budget, actuals pulled on a schedule, committed spend that is approved but not yet invoiced, and a variance view that separates timing from real overspend. Most teams only have the first two, which is why the number is always a surprise: committed spend is invisible until it lands, and a large variance that is really a slow invoice looks identical to a genuine overrun. You can build the whole thing with an AI coding assistant, and the hard part is agreeing what committed means in your company.

budget-tracker.helix-app.ai

Budget tracker

1.84M

Planned, year to date

1.21M

Invoiced

340K

Committed, not invoiced

290K

Actually remaining

1.84M
1.21M
340K
290K
PlannedInvoicedCommittedRemaining

Four bars, never one. The remaining figure alone is the number people quote, and it is the one that needs the other three beside it.

A sketch of the year to date. Committed spend is the highlighted bar because it is the column most budget reports leave out, and the reason a remaining figure is usually wrong.

What matters here

  • A budget vs actuals tracker is four parts: the budget, actuals, committed spend, and a variance view that tells timing apart from overspend.
  • Committed spend is the part teams skip. Approved purchase orders that have not been invoiced are real money already gone, and leaving them out makes every number optimistic.
  • Separate timing variance from real variance. A slow supplier invoice and a genuine overrun look the same in a simple actuals report, and they need opposite responses.
  • Variance is only useful next to an owner. A number with no name attached generates a meeting rather than a decision.
  • Refresh actuals on a schedule rather than on demand. A tracker that is right when you open it and stale by lunchtime trains people to distrust it.
  • A budget tool reads from a finance system of record, so it needs managed credentials and scoped access from the start.

Who this is for

You own a budget, or you run finance for people who do. You already know your chart of accounts and your period calendar. What you want is for a budget owner to see where they stand without asking you, and to see it early enough to change the outcome.

How it works in practice

What a budget owner does with it during a month, and what finance does at the end of one.

  1. 1

    See where you actually stand

    Four numbers side by side: planned, invoiced, committed, and what is genuinely left. Never a single remaining figure on its own.

  2. 2

    Record spend when you commit it

    A signed order is money gone. Log it when you sign, with the date you expect the invoice, not when the invoice lands.

  3. 3

    Let actuals arrive on their own

    The tracker pulls invoiced spend from finance on a schedule and shows when it last succeeded, so a stale number announces itself.

  4. 4

    Match invoices to commitments

    When an invoice arrives it closes the commitment it belongs to, so the same money is never counted twice.

  5. 5

    Read the variance with the reason attached

    Each gap is labelled: on track, a timing difference explained by an open commitment, or a real overrun. Those need opposite responses.

  6. 6

    Freeze the month

    Closing a period locks the figures, so a correction next month cannot quietly rewrite a number somebody already reported.

What a budget tracker is made of

A budget tracker is not a monthly export with conditional formatting. It is four parts, and the third is the one that separates a useful tracker from a rear-view mirror.

The budget

Planned spend by owner, cost centre and period, loaded once and versioned when it is reforecast. Keep the original alongside the reforecast: the gap between them is its own story.

Actuals

What has actually been invoiced and posted, pulled from the finance system on a schedule rather than pasted in. The schedule matters more than the freshness: people trust a number that is reliably a day old more than one that is sometimes live.

Committed spend

Approved but not yet invoiced. A signed purchase order is money you no longer have, and a tracker that ignores it will tell a budget owner they have room they do not have.

A variance view

Budget minus actuals minus committed, by owner, with timing differences flagged separately from real overspend. Variance without that split produces panic about invoices that are merely late.

These prompts start from a Helix project, which is what handles sign-in, credentials and hosting. Start with Helix

The prompts

Paste these into Claude Code, Codex or Cursor in order. Each one leaves you with something that runs, so you can stop after any step.

  1. Budget, actuals, and the number in between

    The two things every tracker has, plus the one that makes them honest.

    In this Helix project, build me a budget vs actuals tracker.
    
    Every budget report I have ever used tells me what I planned and what has
    been invoiced, and both are true, and the remaining figure is still wrong.
    It is wrong because a signed purchase order is money I no longer have and
    nothing shows it until the invoice turns up weeks later.
    
    So build three things, not two. The budget, by cost centre, owner and
    month, loaded from a CSV to start. The actuals, also from CSV for now,
    with a clear route to pulling them from our finance system later. And
    commitments: approved spend that has not been invoiced, with the date I
    expect the invoice to arrive.
    
    Then show planned, invoiced, committed and remaining together, everywhere.
    Never show the remaining number on its own. It is the one people quote and
    the one that needs the other three next to it.
    
    I sign in through Helix, so do not build a login page. Read the signed-in
    user from the runtime. And do not put any key or connection string in the
    code: if this needs to reach another system, tell me and I will create the
    connection in my workspace.

    Worth knowing. Committed spend is the whole design decision. A tracker without it will tell a budget owner they have room they do not have.

  2. Reconciling, so nothing counts twice

    Invoices arriving against commitments already recorded.

    Now handle what happens when an invoice finally arrives.
    
    Let me match it to the commitment it belongs to, so the commitment closes
    and the amount stops being counted in two places. Match on vendor, amount
    and expected date, within a tolerance I can set, and show me the ones you
    are unsure about rather than guessing.
    
    Two lists I want to see. Invoices that match no commitment, which is spend
    that bypassed the process. And commitments well past their expected
    invoice date, which are either late invoices or work that quietly stopped
    and nobody told finance.
    
    Both are short lists and both are findings.
  3. Variance a person can act on

    Telling a slow invoice apart from a real overrun.

    Add the view a budget owner opens.
    
    For each cost centre they own: planned, actual, committed, remaining, and
    the variance as both an amount and a percentage.
    
    Then label each variance rather than leaving it as a number. On track. A
    timing difference, because an open commitment or a known late invoice
    explains it. Or a genuine overrun. Those need opposite responses and a
    plain actuals report cannot tell them apart, which is why every month
    turns into the same meeting.
    
    Sort by the size of the variance in money, not in percent. A 40 percent
    overrun on a small line matters less than 5 percent on the biggest one.
  4. Refresh it, and close the month

    Making it trustworthy enough that people stop keeping their own copy.

    Two last things, and both are about trust.
    
    Refresh the actuals on a schedule and put the time of the last successful
    refresh on every page. If a refresh fails, say so on the screen. A wrong
    number that nobody knows is wrong is worse than no number.
    
    And let me close a month. Closing freezes the figures for that period, so
    a correction posted later shows up in the current month instead of
    silently rewriting something I already put in a board pack.

    Worth knowing. The freeze is what lets the tracker be quoted outside the team. Without it, last month's figure can change after it has been reported.

  5. Connect it to real systems

    The step that turns a working prototype into something with your data in it.

    Now connect it to the systems we actually run, so it works on real data
    rather than the rows you seeded.
    
    Anything in angle brackets is a placeholder. Swap it for whatever we use
    instead, and have the app name the connection it wants rather than assume
    a vendor, so changing my mind later is a config change and not a rewrite.
    
    <NetSuite>. Pull posted actuals on a schedule, which is the difference
    between a tracker and a spreadsheet.
    
    <Coupa>. Read approved orders so committed spend appears before the
    invoice does.
    
    <Okta>. Resolve owners to real people and read their department, so a
    variance has a name attached that survives a reorganisation.
    
    <Slack>. Warn an owner when a cost centre crosses a threshold, rather than
    at month end.
    
    <Looker>. Publish the variance view where finance already looks, rather
    than making them open another tool.
    
    <Snowflake>. Read historical actuals for the trend, which the ERP will not
    give you cheaply.
    
    <Google Sheets>. Import the original plan, because the budget almost
    always starts life in a spreadsheet.
    
    Only write where I have said to write. Everything else is read only.
    
    Do not write a key, a token or a connection string anywhere in the code,
    and do not ask me to paste one. Tell me which connections you need and I
    will create each as an authentication in my Helix workspace. Reference
    them by alias.

    Worth knowing. Every name in angle brackets is a placeholder for whatever you run. Helix holds the credential as a workspace authentication, so the app references an alias and never the secret itself.

  6. Ship it

    The last step of every build: a URL, and the right people on it.

    Deploy my app.

    Worth knowing. Your assistant runs helix deploy underneath and the app comes back as a URL. Budget data is sensitive by owner, so set Access Control before sharing: owners see their own cost centres, finance sees everything.

What it connects to

The budget is yours. The actuals belong to finance, and the whole point is that you stop copying them by hand.

  • NetSuite

    Pull posted actuals on a schedule, which is the difference between a tracker and a spreadsheet.

  • Coupa

    Read approved orders so committed spend appears before the invoice does.

  • Okta

    Resolve owners to real people and read their department, so a variance has a name attached that survives a reorganisation.

  • Slack

    Warn an owner when a cost centre crosses a threshold, rather than at month end.

  • Looker

    Publish the variance view where finance already looks, rather than making them open another tool.

  • Snowflake

    Read historical actuals for the trend, which the ERP will not give you cheaply.

  • Google Sheets

    Import the original plan, because the budget almost always starts life in a spreadsheet.

Each line says whether the app reads, writes or both. Anything not described as writing should be read only.

Named systems are the ones most teams actually run, not a list of the only ones that work. Swap in whatever you use.

Each connection is an authentication in your Helix workspace, referenced by alias. The app names the connection it wants and never holds the credential, so nothing here ends up in your code and any of it can be rotated or revoked without a redeploy.

Running it for real

The build gets you a working tracker. It reads from a finance system, shows spend by person, and will be quoted in meetings, so a few things have to be true before you hand it round.

AI Deployment

Get it to a URL people can open

One command takes the app from your assistant to a live address, so the people who need it get a link rather than instructions for running it locally.

App Security

Scope who sees which budget

Budget data is sensitive by owner. SSO means people sign in with their existing account, and access is scoped so an owner sees their own cost centres rather than the whole company's.

App Security

Connect the finance system without hardcoding a key

The tracker needs to read posted actuals. Managed credentials mean the connection is granted to the app rather than pasted into it, and can be rotated or revoked without a redeploy.

App Registry

Put a name on it

Every app carries a named owner and an entry IT can see, so the tool does not become nobody's problem when the person who built it changes role.

Cost Management

Know what it costs to run

Per-app spend visibility, with budgets and caps, so an internal tool cannot quietly become a line item nobody can explain.

Questions people ask

What is a budget vs actuals tracker?

It compares planned spend against what has actually been spent, by owner and period, so a budget holder can see where they stand before the period closes. A useful one also counts committed spend, which is approved but not yet invoiced, because that is money already gone.

Why does my budget report always look wrong?

Usually because it counts invoices and ignores commitments. An approved purchase order that has not been invoiced does not show up in actuals, so the remaining budget looks healthy until the invoice lands. Tracking commitments separately fixes the largest source of surprise.

How often should actuals refresh?

On a schedule, and show the timestamp. Reliability matters more than freshness: people trust a number that is dependably a day old more than one that is sometimes live and sometimes stale with no way to tell which.

How do I tell a timing difference from real overspend?

Match open commitments and known late invoices against the variance. If the gap is explained by spend that is approved and expected, it is timing. If it is not, it is overspend. They need opposite responses, so a report that cannot tell them apart causes the wrong one.

Should budget owners see each other's numbers?

Usually not by default. Scope access so an owner sees their own cost centres and finance sees everything. That is an access-control decision rather than a reporting one, which is why it belongs in how the app is run rather than in how it is built.

Can I build this without an engineering team?

Yes. The prompts here are written for Claude Code, Codex or Cursor and build it in stages, so you can stop after any of them and still have something that runs. The judgement calls are yours: what counts as committed, and what variance is worth an alert.

Last reviewed September 2026.

Build it, then run it properly

Helix is the governed runtime for AI-built apps. Deploy what you build, put SSO in front of it, connect it to your systems with managed credentials, and give it a named owner.