Your CRM Doesn't Fit Your Business: Why I Built My Own Instead of Buying Salesforce

July 10, 2026

I ran a small B2B distribution business for a while, alongside engineering work, and for the first year it ran on spreadsheets and WhatsApp. Not because nobody had heard of a CRM — because every CRM I looked at wanted me to run my business the way the CRM was shaped, and my business wasn’t shaped that way.

What was actually going wrong

The spreadsheet wasn’t the problem. The problem was that “who owes what” and “what’s actually left in stock” lived in two people’s heads and got reconciled by memory, badly, about once a week. Orders came in over WhatsApp, got written down (or didn’t), and credit terms — some customers paid on delivery, some paid net-30, a couple paid whenever they got around to it — existed as an unwritten understanding rather than a tracked number anywhere.

That’s not a CRM problem in the generic sense. It’s a specific, narrow data problem: three entities (customers, orders, stock) and one relationship that mattered more than any of the standard CRM modules cared about — running balance per customer, against terms that varied per customer.

Why the off-the-shelf options didn’t fit

I trialed two. Both were fine software, built by people who clearly understood CRMs in general. Neither understood this workflow, because it wasn’t the workflow they were built around:

  • Per-seat pricing for a two-person operation that made the monthly cost disproportionate to what the tool actually needed to do.
  • A pipeline/deals model built for a sales team qualifying leads through stages, when what I actually had was repeat B2B customers with standing terms — there was no pipeline, there was a ledger.
  • Generic “custom fields” as the answer to everything workflow-specific, which meant credit terms and partial payments would have lived as bolted-on fields on a data model that wasn’t built to reason about them, instead of as first-class parts of the schema.

None of that is a knock on the tools. It’s that “CRM” is a category name, not a workflow, and the gap between the category and the actual workflow is exactly where the monthly subscription stops paying for itself.

The process: map the workflow before touching schema

Before writing anything, I wrote out the actual sequence of a real order, end to end, the way it happened on WhatsApp:

  1. Customer messages an order.
  2. I check current stock (from memory, badly).
  3. Order gets fulfilled, sometimes partially if stock was short.
  4. Payment happens — sometimes immediately, sometimes 30 days later, sometimes in two partial payments.
  5. Running balance for that customer updates.

That five-step list is the schema, almost directly: customers, orders, order_items against a stock ledger, and payments as their own table against an order rather than a single “paid” boolean — because partial payments were common enough that a boolean would have been lying within the first week.

Order in Stock check decrement ledger Fulfilled full or partial Payment(s) one or many rows customer balance recomputed, not stored

That last note on the diagram matters more than it looks: the running balance is a query, computed from orders minus payments, not a field that gets manually updated. A stored balance drifts the first time someone forgets to update it after editing a payment; a computed one can’t drift, because there’s nothing to forget.

What it’s built on, and why that’s boring on purpose

Laravel, Blade, Alpine.js, MySQL, on shared hosting. No queue workers, no separate frontend build, no infrastructure to operate beyond what shared hosting already handles. That’s a deliberate choice, not a limitation I ran into — this tool has two users and needs to be reliable and cheap to run, not scalable. Reaching for a SPA framework and a managed Postgres instance here would have been solving a problem the business didn’t have, at a cost (both money and my own maintenance time) it didn’t need to pay.

When buying is still the right call

This is the part I’d want someone reading this to actually walk away with, more than the schema details: building your own is the exception, not the default. It made sense here because the workflow was narrow enough to map in an afternoon, the off-the-shelf cost was disproportionate to a two-person operation, and I was going to be the one maintaining it either way, so the “cost” of building was time I already had allocated to this business.

If your sales process actually looks like a pipeline — leads, stages, multiple reps, forecasting — that’s precisely the shape generic CRMs are built for, and you should buy one. The signal that you might be the exception isn’t “I don’t like paying for software,” it’s “I keep describing my process and then adding ‘but not like that’ to every feature the tool offers.”