Skip to content

Part 1 of 7 · Purchase order approver series ~6 min read

A purchase order approver on AWS for a few dollars a month

Someone on your team needs to buy something. They email you. You are on a site visit, so the email waits. Two days later they buy it anyway on a personal card, and now you have a receipt to reimburse, no purchase order, and a budget line that quietly went over without anyone noticing until the month closed. This post walks through the design of a small system that takes the request wherever it arrives, checks it against the budget you already keep in a sheet, approves the routine small ones on the spot, and puts everything else in front of you with the numbers already gathered.

a metal tool box filled with lots of screws
Photo by Dan Crile on Unsplash

Key takeaways

  • Three ways to ask: a reply-to inbox, a short form, and a Slack shortcut. All three land as the same request.
  • Every request ends in one of three states: approved, waiting on a person, or returned for a missing detail.
  • The budget lives in a sheet you already keep. Changing a limit is an edit, not a deploy.
  • It can approve small routine spend only. Above your line, a person decides — always.
  • Designed on AWS for about $3 a month at typical small-business volume.

The whole system on one page

Before any code, here is the shape of what we are designing.

System: three request sources, three pieces inside AWSThree boxes across the top sit outside the AWS account. On the left, Purchase requests: the three ways somebody asks to buy something, which are a reply-to inbox, a short web form, and a Slack shortcut. In the middle, Budget sheet: the spreadsheet the business already keeps, listing budget lines, the spend limit on each, the approved vendors and the auto-approve threshold. On the right, Approver: the person who decides anything above that threshold. Each connects by an arrow to the AWS account container below. Requests flow down into the account. The budget sheet feeds in and grounds every check. The approver receives anything over the line, with the budget position already attached. Inside the AWS account are three components in a row. On the left, the Intake, which receives requests from all three sources and turns each into one consistent shape: who asked, what for, which budget line, how much, and which vendor. In the middle, the Checker, which reads the request against the sheet and answers four questions: does that budget line exist, is there room in it, is the vendor known, and has this same request come through before. On the right, the Router, which either issues a purchase order for small routine spend or sends the request to the approver. Arrows flow left to right between them. A note at the bottom says no money moves without a person above your limit; the system only ever proposes.AWS ACCOUNTPurchase requestsinbox, form, SlackBudget sheetlines, limits, vendorsApproverdecides anything bigIntakeone shape forevery requestCheckerbudget line, room,vendor, duplicatesRouterapprove small,ask about the restrequests ingrounds everycheckanything over thelineNo money moves without a person above your limit -- the system only ever proposes.
Fig 1. Three things outside the account, three pieces inside it. Requests arrive from an inbox, a form and a Slack shortcut. The checker reads the budget sheet and lands on approve, ask or return. The router either issues the small routine ones or puts the rest in front of a human.
  • App integration
  • Machine learning
  • Analytics
  • Front-end & mobile
  • People

What you set up once (the outside)

  • Purchase requests. Three ways to ask, all covered in Part 2. The first is an inbox — somebody emails a dedicated address the way they already email you. The second is a short form on your intranet, five fields long. The third is a Slack shortcut for the people who live there. All three end up as the same record: who asked, what they want, which budget line it belongs to, how much, and which vendor.
  • A budget sheet. One tab you almost certainly already keep. Each row is a budget line — “Workshop consumables”, “Site fuel”, “Software” — with the amount for the period, the amount committed so far, the people allowed to spend against it, and the auto-approve threshold for that line. A second tab lists approved vendors. The sheet is the source of truth. If a line is not in the sheet, the system will not invent it; it returns the request and asks which line it belongs to.
  • An approver. The person who owns the money. They get a short message per request — what, how much, which line, how much is left in that line after this, and whether this vendor has been used before — with two buttons: approve and decline, plus a box to ask a question. They are not reading a form. They are reading a number and a name.

What runs on every request (the inside)

  • The intake. Three sources feed one queue. An email is messy prose; a form is already structured; Slack is somewhere in between. The intake turns all three into the same five fields, and this is the one place a model earns its keep — reading “can I get another two boxes of the blue gloves from Medline, same as last time” and coming back with a vendor, a quantity, and a best-guess budget line. If it cannot fill a field with confidence, it leaves the field empty rather than filling it in with something plausible.
  • The checker. Runs once per request and asks four plain questions against the sheet, in order. Does this budget line exist? Is there room in it for this amount? Is this vendor on the approved list? Has this same request already come through today? Each answer is a yes or a no with the number that produced it, so the decision can be read back later. None of this is the model’s job — it is arithmetic against a sheet, and plain code does arithmetic more reliably than any model will.
  • The router. Reads the four answers and picks one of three outcomes. All four yes and under the line’s auto-approve threshold: issue the purchase order, write it to the ledger, tell the requester. All four yes but over the threshold: send it to the approver with the budget position attached. Any no: return it to the requester saying exactly which check failed and what would fix it. Nothing is ever silently dropped.

One request, end to end

Here is the same system as a single line, which is how it actually feels to use.

One purchase request from arrival to commitment, in five stagesA horizontal row of five boxes joined by arrows. First, Asked: the request arrives by email, form or Slack. Second, Read: the request is turned into five fields, which are requester, item, budget line, amount and vendor. Third, Checked: the budget line, the room left in it and the vendor are all verified against the sheet. Fourth, Decided: either the amount is under the auto-approve threshold and the system issues it, or a person decides. Fifth, Committed: the purchase order goes out and the committed column on the budget line moves. A note below says five stages, and the fourth is the only one where a person is ever required.ONE PURCHASE REQUEST, END TO ENDAskedemail, form, SlackReadinto five fieldsCheckedline, room, vendorDecidedauto or a personCommittedPO out, line updatedFive stages. The fourth is the only one where a person is ever required.
Fig 2. The same system as one line. A request is asked for, read into a fixed shape, checked against the sheet, decided either automatically or by a person, and then committed — which means a purchase order goes out and the budget line moves.
  • App integration
  • Machine learning
  • Analytics

In plain words

Your workshop lead needs gloves. She emails the requests address: “another two boxes of the blue nitriles from Medline please, same as last month, about 90 dollars”. The intake reads that into five fields: requester her, item two boxes of nitrile gloves, vendor Medline, amount 90 dollars, budget line Workshop consumables. The checker opens the sheet. Workshop consumables exists. It has 1,240 dollars left this quarter, so there is room. Medline is on the approved list. Nobody has asked for the same thing today. All four are yes, and 90 dollars is under the 250-dollar auto-approve line you set on that row. So the router issues the purchase order, emails it to Medline, replies to her with the PO number, and moves the committed column from 760 to 850. Total elapsed time: under a minute, and you never saw it.

The following week she needs a replacement bench grinder, 640 dollars. Same three checks pass, but 640 is over the line. So instead of issuing it, the router sends you one message: what it is, who asked, which line, and the sentence that actually matters — “Workshop consumables has 1,150 left this quarter; this would leave 510.” You tap approve on your phone at the traffic lights. The PO goes out. That is the whole difference between this system and an inbox: the inbox gives you a request, and this gives you a request and the consequence of saying yes to it.

Design rules that shaped every decision

  • A person decides anything above the line. The system can issue small routine spend and nothing else, and the line is a number you write in the sheet.
  • The sheet is the source of truth. The system reads budget lines, limits and vendors from it and never invents one that is not there.
  • Every answer ships with the number behind it. “No room” always comes with how much is left and how much was asked for.
  • Empty beats plausible. When the intake cannot read a field confidently, it leaves it blank and asks, rather than guessing a budget line.
  • One request, one purchase order. A fingerprint on requester, vendor, amount and day makes a resend land on the same request instead of a second one.
  • Nothing is silently dropped. A failed check returns to the requester saying which check failed and what would fix it.

Why this shape

Most small teams run purchase approval one of two ways. Either everything goes through one person’s inbox, which works until that person is on a roof or on a plane, and then the whole business waits on them for a 90-dollar box of gloves. Or there is no process at all, people buy what they need and hand in receipts, and the budget is a thing you discover at month end rather than something you steer. The first is a bottleneck; the second is not a system, it is a hope.

The shape above keeps the budget where the business already keeps it — a sheet — but puts a small, fast, boring layer in front of it. The layer is allowed to do exactly one consequential thing on its own: issue small, routine, in-budget, known-vendor purchase orders. Everything else it turns into a one-tap decision with the number attached. It does not need to be clever to be worth having. It needs to be quick, honest about what it does not know, and completely unwilling to spend money above a line you drew.

The next four posts walk through each piece in turn: how a purchase request arrives, how it gets checked against the budget, how an approval reaches the right person, and how the money actually gets committed. One diagram per post, a cost breakdown, and an engineering reference at the end.

All posts