top of page

The 8-Item Checklist I Use Before Buying CRM Source Code

  • Andrew Jenkins
  • May 16
  • 3 min read

I've audited about a dozen CRM codebases for clients over the last couple years. Here's the checklist I actually use, posting in case it helps anyone evaluating one right now.


These are the 8 things that get skipped on every "production-ready" demo I've seen. The demo is always pretty. The bones usually aren't.


1. The license. Read it twice.


"You get the source code" doesn't mean you can resell, sublicense, white-label, or even redeploy under your own brand. I've seen source-available licenses that ban competing products, ban SaaS resale, or quietly require revenue share over a threshold. If the seller can't show you the exact license text before you wire money, walk.


2. Multi-tenancy. How is it actually implemented?


Row-level (tenant_id on every table), schema-per-tenant, or DB-per-tenant? Each has real tradeoffs. Row-level with no enforced policies at the DB layer means one missing where-clause leaks every tenant's data to every other tenant. Ask to see the middleware that scopes queries. If they can't point at it in 30 seconds, the answer is "it isn't really scoped."


3. Auth and session handling.


JWT in localStorage? Session cookies? Refresh token rotation? Password resets that actually expire? I once reviewed a codebase that stored API keys in plaintext in the users table. Seller called it a feature.


4. The migration system.


How do you get from v1 schema to v2 without nuking client data? If there's no migration framework (Prisma, Drizzle, Knex, Alembic, Rails migrations, whatever) and the answer is "we just run SQL scripts manually," that's a no.



5. Background jobs.


Email sends, webhook retries, scheduled automations, reminder workflows - none of that should run in the request lifecycle. Look for a real queue. If "send 500 reminder emails" blocks the API, you don't have a CRM, you have a toy.


6. Email/SMS deliverability.


Custom SMTP per tenant? SPF/DKIM/DMARC docs? For SMS in the US, is A2P 10DLC registration handled or is that your problem? This is the boring infra that decides whether your clients' messages land in inbox or spam. Nobody demos it. Everybody gets bit by it.


7. Webhooks and idempotency.


Inbound webhooks from Stripe, Twilio, calendar providers - are they idempotent? Do they verify signatures? Do failed webhooks retry with backoff? I've seen codebases that just trusted any POST to /webhook/stripe. That's how you process a refund nobody asked for.


8. Update path.


After you buy, how do you get bug fixes? Private git access? Quarterly zip drops? Nothing at all? If you're forking and never pulling upstream again, fine, but know that going in. Don't assume there's a maintenance relationship if it isn't written down.


The decision rule I use


If I'd have to rewrite more than ~30% of the code to ship it to a paying client, I pass. Doesn't matter how cheap it is. The rewrite eats every dollar you saved plus six months of your life.


When the checklist saved me


A client wanted to buy a $4k codebase last spring. Demo looked clean. Checklist found row-level multi-tenancy with no scoping middleware (item 2), and the license forbade reselling under their brand anyway (item 1). We walked. They were annoyed with me for a week, thanked me a few months later when the seller got sued.


When I ignored it and got burned


Skipped item 5 on an internal build a while back. Shipped without a real job queue because "we're small, it'll be fine." It was not fine. Spent two weekends rebuilding it under load while clients were yelling at me about missing automations.


I ended up building my own from scratch this year because I kept finding the same gaps in everyone else's codebases. 800ish hours in now. Probably not the right answer for most people, but at some point the audits stopped being worth the time. I wrote up the longer version of why I went build-over-fork here: https://seedlycrm.com/blog/build-your-own-crm-why-you-should-fork-instead

 
 
 

Comments


bottom of page