· Updated  · build vs buy

Build vs Buy: What Per-Fill Margin Actually Takes

The weekend-project version is revenue minus cost. Seven problems sit underneath it, and knowing them tells you whether to build this yourself or buy it.

If you have an analyst, a data warehouse, or a son-in-law who writes SQL, someone has already suggested it: we do not need a vendor, margin is revenue minus cost, we can build it.

They are right about the formula. They are usually unaware of the seven things underneath it. A pharmacy that reads this and builds anyway has made a good decision with open eyes, which beats a purchase resented in month three.

Problem 1: getting the events at all

Margin arithmetic is downstream of a data feed, and the feed is most of the work.

A nightly export gets you month-end analysis. It will not flag a fill before the wholesaler order goes out. Real-time means subscribing to events as adjudication happens, and that means a credential, an endpoint that is up when the pharmacy is open, and a plan for the hours it is not.

Then the parts nobody scopes:

  • Redelivery. Your endpoint is down for six hours and the source retries. Do you now hold one copy of each event, or three?
  • Idempotency. The answer is a stable key derived from the event plus a unique index that lets the database reject the duplicate. Checking first and inserting after races with itself under concurrent retries.
  • Backfill. After an outage the gap must be filled, and you need to know it was.

None of this is exotic. All of it is a week nobody planned.

Problem 2: whether you archive before you parse

Get this wrong and you will not find out for a year.

The tempting design reads the payload, extracts the fields you care about, writes a tidy row, and discards the rest. It works until your first parsing mistake. Then the data needed to correct it is gone, and nobody can send it to you again.

The alternative stores every payload exactly as received, before anything interprets it, and treats everything downstream as a projection you can recompute. A parsing bug becomes a replay instead of a permanent hole. The same archive is what makes an audit request about claims from fourteen months ago answerable.

If you build, archive first. Storage is cheap. Being wrong recoverably is not.

Problem 3: the arithmetic is a floating-point trap

Margin subtracts two nearly equal numbers, which is where binary floating point is proportionally worst. Error that was negligible against each input is not negligible against the difference.

The canonical example: in most languages, taking 8.115, multiplying by 100 and rounding gives 811 cents rather than 812, because the stored value was never really 8.115. Across a month of fills your report is then wrong by an amount that is small, real, and impossible to explain to an accountant.

Hold every money value as an integer number of cents from ingestion to display and never let a float touch it. That is a discipline more than a line of code, so write a test that fails the build when a money-named column is typed as a float.

Problem 4: cost is the hard half

Reimbursement arrives on the adjudication response. Cost does not.

To compute margin you need what you actually paid for that NDC in that package size. That means ingesting wholesaler invoices, matching them to dispensed products, and handling the mismatches:

  • NDC formats. The same product appears as a 10-digit code in one place and an 11-digit code in another, with the zero padded into a different segment depending on the labeler/product/package split. Matching without normalising is how a drug ends up appearing to have no cost.
  • Package versus dispensed quantity. Your invoice prices a bottle of 90 and the fill dispensed 30. Scaling is easy, but rounding on every line accumulates error across a month, so round once at the end.
  • The fallback. Without an invoice, NADAC is the usual substitute and carries its own caveats. It is a survey of retail community pharmacy invoice prices that excludes mail order and specialty, and it excludes rebates and off-invoice discounts received after the invoice is paid. Since the December 2024 updates, CMS has calculated monthly generic rates on a three-month moving average to damp volatility from fluctuating survey participation. It is a benchmark, not your cost, and a system that does not say which it used will be believed as though it were.

Problem 5: deciding what to show when you know nothing

Then there is the fill with no cost on file at all.

The lazy implementation treats a missing cost as zero. Every such fill reports as pure profit. That is wrong in the most expensive available direction, because it hides losses rather than raising false alarms, and the report looks healthiest exactly where your data is worst.

Compute no margin, say so, and flag the fill as needing a cost. More code, a less satisfying dashboard, and a number you can act on instead of one that will eventually embarrass you.

Problem 6: the cases that are not a simple fill

  • Reversals, and partial fills later completed.
  • Secondary and coordination-of-benefit claims, where more than one payer contributes and revenue for one fill arrives in pieces.
  • 340B and other contract pricing, where the invoice cost is not the cost that applies.
  • Post-adjudication adjustments, which still exist in various forms depending on the line of business and arrive long after the fill.

Each is a rule. None is impossible. Together they separate a prototype that works on the happy path from a system your controller will sign off on.

Problem 7: it has to keep running

The cost that never appears in the estimate. Your pharmacy system gets upgraded. A field changes name. A new payer starts populating a field that was always empty. The endpoint certificate expires on a Saturday. Someone has to own that, and if your build has one author who then leaves, you have a reporting outage and nobody who can read the code.

When building is genuinely right

Buying is not automatically correct. Here is where we would tell you to build.

  • You already have the warehouse and the people. If prescription data already lands somewhere you control and someone competent owns it, the marginal cost of margin logic is far lower for you than the market price.
  • You need it joined to things a vendor cannot see. Payroll, delivery costs, your general ledger. A vendor computes margin on the fill. Only you can compute profit on the store.
  • Your contracts are unusual. Chains, 340B contract pharmacy arrangements and LTC operations often have economics a general product models badly.
  • You want no vendor in the data path. A legitimate position, and one no amount of security documentation should have to argue you out of.

When buying is right

  • The value is in acting within minutes, and you do not want an on-call rotation for a webhook.
  • Nobody on staff will own it in eighteen months.
  • You want the cost basis problem solved by someone whose full-time job it is.
  • You would rather spend your one scarce technical person on something that differentiates your pharmacy. Margin arithmetic does not.

What buying from Attergo gets you

The platform is eight products on one event spine: Margin, Billing, Audit, Authorizations, Inventory, Compliance, Intelligence, and Integrations, which is the spine itself. Connect it once and the others switch on later without a second integration project in your store.

That spine runs end to end: real-time ingestion from PioneerRx’s Rx Event API with a per-store credential, an immutable archive of every payload as received, and per-fill margin against acquisition cost from your wholesaler invoice or NADAC, with the basis and its confidence shown on every fill.

The real comparison is not a margin query against your SQL. It is a maintained, evidence-grade platform against a side project that has to survive staff turnover, payload changes and every audit that arrives after the person who wrote the script has left.

The middle path most people miss

You do not have to choose completely. Ask any vendor for a structured export of your own normalised events, and check the contract says you can have it. Let them run the ingestion, the idempotency, the archive and the cost matching, then build your own analysis on the clean output.

The part that is genuinely hard to operate becomes somebody’s full-time job, and the part specific to your business stays yours. If a vendor will not agree to that export, you have learned something more useful than anything in their demo.

Ours will. See what Attergo Margin computes and what Attergo Integrations hands back, then decide which half you want to own.

Run this on your own claims.

Attergo prices every fill against the contract that governs it and shows you the gap before the fill leaves the counter.