About Compoundly
Ordering software for veterinary compounding pharmacies, built around the one thing that cannot go wrong.
The problem
Compounding pharmacies run their ordering on tools built for selling t-shirts. The prescription — the thing that makes dispensing legal — ends up as a note in a comment box, a custom field, or a line-item property that quietly disappears the moment somebody edits the order.
We watched this happen in a real pharmacy. Changing a flavor on an order meant deleting the line and adding it back, and the patient and prescription went with it. Per-customer pricing drifted until nobody could say what a given clinic should be charged. Phone orders were placed by staff logging in as the vet, so the record said the clinic ordered something the clinic had never touched.
None of that is a training problem. It is what happens when the software does not know what a prescription is.
The approach
Compoundly has one rule, and it lives in the database rather than in application code: an order line cannot exist without an authorization behind it. Every other design decision exists to keep that rule sufficient.
- An exception never becomes a line item directly. A supervisor approving one writes a real authorization, and only then can the item exist — as a single transaction that either completes or does nothing.
- Editing a line item never touches its authorization. Quantity changes update quantity; flavor and size changes update the variant on the same row.
- Every request for an exception is permanent, approved or denied, so “did somebody try to add this without a script” always has an answer.
- Each pharmacy’s data is isolated by row-level security in the database, not by a filter in application code that somebody can forget to write.
What it deliberately does not do
Several things are left out on purpose, because the more capable version was tried in a real pharmacy and caused real damage: per-customer price overrides on top of tiers, splitting one order across multiple addresses, and automated hold timers that move stock without a person deciding to.
Pharmacist verification is a stage you can use but are not forced through, because the pharmacy we build with does not work that way today. It changes nothing about the rule above — the database refuses an unauthorized item at every stage, verified or not.
What that looks like in practice
These are real Postgres errors, not messages the application chose to print. The write is refused whether it comes from the product, an import script, or someone at a SQL prompt:
-- an order line with no prescription behind it INSERT INTO order_line_items (order_id, catalog_item_id, authorization_id) VALUES (…, …, NULL); ERROR: null value in column "authorization_id" violates not-null constraint -- a prescription invented on the spot INSERT INTO order_line_items (…, authorization_id) VALUES (…, gen_random_uuid()); ERROR: insert or update on table "order_line_items" violates foreign key constraint
Application code can have bugs. A NOT NULL column with a foreign key cannot be talked out of it. Compoundly ships with a test suite that proves this against the live database on demand.
Where it is
In active development with a design-partner pharmacy, running against their real catalogue, real customer accounts, and years of real order history. We are talking to a small number of additional compounding pharmacies now.