Product or custom build: the day you fork the code, your product dies

The sentence that kills more products than any strategic decision is a small concession said in a meeting: for this client it is just a tiny change in the code. It sounds harmless, generous even. But the day a per-client version of the code exists, the product is dead, and what remains, without anyone announcing it, is a services business priced like a product.

The idea that organises everything else: configuration, never code. Everything that distinguishes one client from another, their catalogue, prices, zones, hours, tone and rules, has to live in configuration rather than in a branch of the program. If selling again forces you to touch a line of code, you do not have a product. You have a custom build you are charging for as though it were one.

What separates a product from a custom build?

Where the difference between clients lives. In a product, everything that varies sits in configuration and the code is identical for all clients. In a custom build, each client has their own version. The consequence is economic: an improvement either reaches everyone at once, or it gets applied client by client, forever.

What it isWhere it must live
Catalogue, prices, zones, hoursConfiguration
Tone, copy, business rulesConfiguration
Payment details and credentialsConfiguration, per client, isolated
The logic that solves the problemCode, identical for everyone
An exception “just for this client”Nowhere: it is either configuration, or it is the product

This is the same line that separates architecture from modules, seen from the commercial side. The last row is the hard one, and it is where products get lost. Every exception resolved by touching the code looks cheap on the day it is made and gets paid for over years.

The arithmetic that kills margin

The cost of forking the code is not paid when you fork it. It is paid in everything that happens afterwards. With a single codebase, fixing a bug costs once and every client is fixed. Shipping an improvement costs once and everyone improves.

With one version per client, each bug exists in as many versions as you have clients, and each improvement has to be ported, tested and deployed one at a time. That turns maintenance into a function that grows with sales, which is precisely the opposite of a product. In a product, client number twenty adds almost no maintenance. In a forked build, client twenty adds a twentieth more of everything, permanently.

The financial symptom is unmistakable and it arrives late: revenue grows and margin does not. By the time it is visible on a spreadsheet, the fork is two years old and unwinding it costs more than the clients are worth.

What this looks like on GoHighLevel

The platform is unusually good at this distinction, and unusually easy to break it on.

The configuration layer you already have

Custom values hold per-client constants. Custom fields hold per-client data. Snapshots hold the shape of a working account. SaaS Mode holds the commercial packaging. Between them, most of what varies between clients has a designated home that is not code.

Where the fork actually happens

Rarely inside the platform. It happens in the middleware: a webhook handler with a condition for one client, a script that treats one sub-account differently, an integration hardcoded to a single sub-account identifier. Each of those is a branch, and because it lives outside the platform nobody counts it as one.

The test is simple. If onboarding client twenty-one requires you to open an editor rather than fill in values, the fork already exists. It just has not been named yet.

Onboarding as the script that proves it

The honest way to find out whether you have a product is to write down the steps to onboard a new client. Not the sales steps, the technical ones. If the list is entirely made of values to enter (name, catalogue, credentials, hours, zones) you have a product. If anywhere in that list there is a step that says “adjust the code for their case”, you have a custom build with a subscription attached.

That script is also the fastest thing to improve. Every step you move from judgement to configuration is a step someone else can execute, and delegation is only possible once the steps stop requiring you.

The honest limits: what stays manual, and why

Not everything should be configurable, and pretending otherwise produces a different failure: a configuration surface so large that nobody can operate it. Some things stay manual on purpose.

  • Anything requiring a legal or commercial decision. Approving a price exception is judgement, not a toggle.
  • Third-party approvals. Messaging templates going through review, domain verification, payment onboarding. You cannot automate somebody else’s queue.
  • The first configuration of a genuinely new client type. The second one is a template. The first one is design work, and rushing it is how a bad shape gets replicated twenty times.

Declaring these openly is what keeps the product honest. The problem is never that something is manual. The problem is a manual step nobody documented, discovered by the person doing it at eleven at night.

When a custom build IS the right call

There are cases where forking is the correct commercial decision, and refusing to see them is its own kind of dogma. A single client paying enough to fund a dedicated build, with a contract that prices the maintenance, is a services engagement and should be sold as one. A regulated sector whose requirements genuinely cannot coexist with the shared logic is another. And a deliberate prototype, built to learn and scheduled for deletion, is fine as long as the deletion date is real.

What is never right is the accidental version: forking without deciding to, without pricing it, and without telling the client that from now on their system is theirs alone to maintain.

Common mistakes when building for many clients

  • Treating the first exception as free. It is the cheapest one you will ever make and it sets the precedent for all the rest.
  • Confusing a snapshot with a product. A snapshot replicates a shape. It does not give you one place to fix things, which is the actual property you want.
  • Hardcoding an account identifier. The single most common fork in practice, and the one that looks least like one.
  • Charging a product price for a bespoke maintenance obligation. The margin does not disappear at once; it erodes one client at a time.
  • Not documenting the configuration surface. If only you know which value does what, the product is still in your head, whatever the code looks like.

Not sure whether you are selling a product or maintaining twenty builds?

The architecture service decides that boundary before somebody builds it: what lives in configuration, what lives in code and what must live outside the platform. The deliverable is the map in writing, from USD 1,800. Everything runs in writing, in English, and the first reply arrives within one business day.

See the three services

Frequently asked questions

What is the difference between a product and a custom build?

Where the difference between clients lives. In a product, everything that varies sits in configuration and the code is identical for all clients, so one fix reaches everyone. In a custom build, each client has their own version, so every fix and every improvement has to be applied one by one. The distinction is economic before it is technical.

How do I know if I already forked without noticing?

Write the technical onboarding steps for a new client. If any step involves opening an editor instead of entering a value, the fork exists. In practice it usually sits in middleware rather than in the platform: a webhook with a condition for one client, or an integration tied to one account identifier.

Can I go back once the code is forked?

Yes, and it gets more expensive every month. The path is to identify what actually differs between versions, move each difference into configuration, and converge the branches one at a time. It is unglamorous work with no visible output for clients, which is exactly why it keeps getting postponed until it is unaffordable.

Is a snapshot enough to have a product?

No. A snapshot copies a configuration into a new sub-account, which speeds up setup and replicates the original design faithfully, errors included. What it does not give you is a single place where a fix applies to everyone. Twenty accounts cloned from one snapshot are still twenty accounts to correct.

Where should per-client credentials live?

In configuration, isolated per client, and never in the code or in a shared file. Beyond the security reason, credentials in code are a fork by definition: adding a client means editing the program, which is the exact property a product is supposed to avoid.


Written from building multi-client systems on GoHighLevel in production, August 2026. The principle predates the platform; the failure modes described here are the ones that show up on it.

The idea that keeps the product alive

A product is not defined by having many clients. It is defined by whether one change reaches all of them. That property is fragile, it is destroyed by a single well-meant exception, and nobody sends a notification the day it breaks. The discipline is to keep asking, every time a client wants something different, whether the answer belongs in configuration or whether it belongs in the roadmap for everyone. Those are the only two honest answers. The third one, just for this client, is the one that quietly turns a business you can scale into a business you have to staff.

Picture of Alexander González

Alexander González

Es Arquitecto de Sistemas CRM y Especialista en GoHighLevel. Fundador de Alex González GO y creador de Marketing Nativo. Trabaja desde el diagnóstico B2B y la gobernanza de datos antes de automatizar, bajo la firme premisa de que la tecnología debe sostener y escalar las operaciones, no reemplazarlas.

Más información - Whatsapp

Últimos posts

Transparencia: algunos enlaces de este sitio son de afiliado. Si contratas a través de ellos, Marketing Nativo recibe una comisión sin costo adicional para ti; es parte de cómo se financia este contenido. Marketing Nativo es un sitio independiente y no está afiliado oficialmente a HighLevel Inc. GoHighLevel y HighLevel son marcas de sus respectivos propietarios.