Payroll tooling: why we extracted payroll from spreadsheets

Payroll tooling: why we extracted payroll from spreadsheets

Payroll for a ten-person shop should not take a Friday afternoon. The math is simple — rates, hours, deductions, net. The complication is everything around the math: which spreadsheet has the current rates, which tab holds last quarter's adjustments, which contractor changed banks. We were tired of the spreadsheet doing the bookkeeping and us doing the work around it. So we built a tool, and we open-sourced it.

This is the story of why we stopped doing payroll in spreadsheets and built a simple tool instead — and why we open-sourced it.

The Spreadsheet Problem

If you run a small team, you know this. Payroll starts as a spreadsheet. Someone joins, you add a row: name, hourly rate or salary, payment frequency, tax withholding. Every two weeks, you calculate hours, apply the math, and cut a payment. That works for a while.

Then it grows. You have contractors in different states, each with different tax withholding requirements. You have part-time people who work varying hours, and you need to track their time against projects. You have bonuses, reimbursements, and one-time payments that don't fit the regular template. Suddenly your simple spreadsheet has three different calculation tabs, manual adjustments that nobody remembers, and everyone asking you to verify something about their last payment.

The thing about spreadsheets is they're perfect until they're not. They work for simple use cases, but they degrade fast as complexity grows. The moment you need conditional logic — if contractor is in state X, apply tax rule Y — you're writing formulas that nobody else understands. The moment you need audit trails, you're hoping someone remembers to date-stamp their changes. The moment you have multiple people touching the file, you're one accidental overwrite away from a complete mess.

We hit that wall. Not dramatically — no payroll crisis, no missing money. Just a growing sense that we were one bad formula away from a problem.

What We Actually Needed

Instead of building a full payroll system, we needed something much simpler. We needed:

- Employee records: Who works for us, what's their payment type, what's their tax setup. - Pay periods: Running payroll for a specific date range. - A way to calculate gross pay: Hours worked times rate, or salary divided by pay periods. - A way to record taxes withheld: Simplification of tax calculations for now. - A final net pay number: What actually goes to the person. - An audit trail: Who was paid what, when, and by whom.

That's it. We weren't trying to replace ADP, Gusto, or any of the established players. We were trying to replace a spreadsheet, not an enterprise HR platform. The moment you try to build the latter, you've consumed far more time than you saved.

We called this the bounded problem: payroll-adjacent enough that spreadsheets were painful, simple enough that full HR software was massive overkill. We needed just enough tooling to run payroll accurately without any of the HR, benefits, compliance, or reporting features that make payroll software complicated.

Boundaries of v1

When we sat down to build, we drew explicit lines around what v1 would include:

- Employee management — add, edit, deactivate. Name, payment type (hourly or salary), hourly rate or salary amount, tax jurisdiction. That's it.

- Payroll runs — select a pay period, enter hours for hourly employees, let the system calculate gross. Enter tax withholdings, let it calculate net. Record the payroll run with a timestamp.

- Records — see who was paid what, when. No reports beyond a simple list. No exports beyond CSV.

That's v1. It doesn't do:

- Tax filing or remittance (we still file manually) - Benefits or compensation tracking - Multi-state compliance beyond what's in your head - Anything involving direct deposit (we handle that manually for now) - Employee onboarding workflows

We were explicit about these boundaries because we learned from past feature-creep mistakes. The tool exists to replace a spreadsheet, not to become a company. If you need more than what v1 does, you probably need a real payroll provider, not a custom tool.

The Stack Choice

We built this as a simple PHP web application with SQLite for storage. No external database, no complex setup, no dependencies. The entire application is a handful of PHP files, a small SQLite database, and nothing else.

Why that stack? Two reasons:

First, we wanted to run it ourselves with minimal operational overhead. A VPS with PHP and SQLite — that's a $5-a-month server, and it runs fine. No external services to pay for, no database migrations to manage.

Second, we wanted to open-source it. PHP and SQLite are universally readable — anyone looking at the code can verify what it does. There's no proprietary framework hiding anything. If you want to deploy it yourself, you can. If you want to modify it, you can.

The repository is public on GitHub under an open license (decisionsciencecorp/payroll). That's the entire point: we wanted something other small teams could use without a $50/month SaaS subscription or a custom build from scratch.

What Integrators and Operators Get

For operators running small teams, the tool does exactly what the spreadsheet did, but correctly:

- Accurate calculations. No more formula errors in your spreadsheet. The math is code, and it runs the same every time. - Audit trail. Every payroll run is recorded with who ran it and when. If you need to verify what happened in March, you have the record. - Employee history. Every employee's payment setup is stored, not in someone's memory or a verbal agreement. - CSV export. When your accountant needs the quarterly numbers, you can give them a clean file.

For integrators, it's even simpler: it's a read-write REST API. Create an employee via POST, run payroll via POST, fetch records via GET. If you need to build payroll into your own workflow, the API gives you that.

Honest Limits

We want to be clear about what's not here — and why:

This isn't ADP replacement. We don't handle tax filing, remittance, or compliance. We're not going to. That's a massive regulatory undertaking that takes full-time teams. If you need ADP, Gusto, or a professional payroll service, use one. This tool is for people who were using spreadsheets and want something slightly better.

We don't do direct deposit. Not because we couldn't, but because storing bank account information in a small PHP app with no compliance certification seemed like a bad idea. We handle payments manually — check, Venmo, whatever — and the tool just tells you what to pay.

Multi-state is limited. We handle one tax jurisdiction in the code as an example. If you're in multiple states, you'll need to extend it. We made that easy by design — the tax calculation is a single function you can replace — but it's not pre-built.

These limits are features. We wanted v1 to be small enough that anyone could understand it in an afternoon, not bloated enough to compete with Gusto. If you outgrow it, that's a good problem to have.

Close + CTA

We built this tool because we were tired of spreadsheet payroll. We open-sourced it because other small teams probably are too.

If you're running a small operation — an agency, a consultancy, a small team of contractors — and you're still doing payroll in spreadsheets, this might be for you. It lives on GitHub (decisionsciencecorp/payroll). Clone it, deploy it, let us know what you think.

If you need something more robust, we're not the answer — go use Gusto or ADP. But if you just need your payroll out of spreadsheets and into something you actually understand, we'd rather you use this than keep using Excel.

The repo is public. If payroll or ops data is eating spreadsheet time at your company, tell us what decision you are trying to make—we help when manual analysis stops scaling.