Yes, you can build an application on Open Mercato that has nothing to do with selling goods online. We did, and this article is the receipt: our own outbound sales operation, running in production on the platform, with the numbers it carries as of 9 October 2026.
thegoodcode is a software house in Gdansk. We build CRM, ERP and configuration systems for manufacturers, and we are a certified Open Mercato partner and an open source contributor. Open Mercato is an open source application framework: multi-tenancy, role based access, an audit trail, custom entities and a set of business modules that you extend instead of replacing.
Most writing about Open Mercato, including ours, describes what it ships for commerce. We have already published a walk through of what the CRM module gives you out of the box. This article is narrower and, we think, more useful to anyone evaluating the platform for a system that is not a shop. Below is what sits in the platform, what we wrote ourselves, and the real numbers.
Why we did not buy a CRM for this
We had the usual options. A seat-priced CRM with a pipeline view. A spreadsheet. A lightweight outreach tool bolted to LinkedIn.
The thing that ruled all of them out was the shape of our data. Our funnel is a graph of people, the companies they work for, the evidence we have gathered about those companies, a scoring profile that turns that evidence into a verdict, and a ledger of every touch. A person can belong to a company that we have never contacted. A company can carry several live threads at once. Evidence about a company has to flow down to every person who works there, and it has to be timestamped so that a verdict can be recalculated when the evidence changes. A list of deals moving through stages holds none of that.
Off-the-shelf tools model the people and the companies, then give you a custom field box for everything else. We wanted the scoring evidence to be a first class record with its own history, because the question we ask most often is "why does the system think this company is a fit, and when did it last check", and a stage field cannot answer it. This is the same argument we made for integrations generally in the data model decides whether your systems can integrate, applied to a system we were buying for ourselves.
There was a second reason, and it was about ownership. We sell systems that clients own. Running our own operation on rented software while telling clients to own theirs is an argument we did not want to make.
What Open Mercato gave us, and what we wrote ourselves
Open Mercato covers the parts of the problem that are the same for everybody. Authentication and sessions. Role based access where the unit you grant is a feature. Multi-tenancy switched on by default, with queries scoped automatically. The audit log stores a snapshot before and after each write together with the actor, and the custom entities module lets you define your own record types and get forms, lists and an API without touching the core. On the v0.9.0 release tag of 9 October 2026, the core carries 48 modules with 40 supporting packages around them, and both the repository and the core package are MIT licensed.
Our own work is one module, and it is smaller than people expect: 247 TypeScript files.
Four core record types we reused
Four customer record types came from the core and were reused instead of rebuilt. A customer entity, a person profile, a company profile, and the link between a person and a company. That link mattering as its own record is the reason we did not have to flatten "works at" into a text field on the person.
Fourteen entity types of our own
On top of those we declared 14 entity types of our own, all under an outreach: namespace, with 145 field definitions between them:
outreach_event, the ledger. Every invitation, accept, message, reply, comment, note and state change is recorded here with a timestamp and a channel.icp_fact, one measured fact about a company or a person, with a source, a reference and a confidence. Facts are versioned, so a correction supersedes the earlier reading and both stay readable.icp_evaluation, the computed verdict, score and coverage for one subject under one profile.icp_rule,icp_parameterandicp_profile, the scoring model itself, expressed as data instead of as code.icp_override, a human decision that outranks the computed verdict.person_alias, because the same person arrives from several sources under several identifiers.acquisition_source,signal,gtm_week,linkedin_account,org_content_eventandpaid_run.
That last one is worth a sentence. paid_run records every enrichment call that costs money, written behind a guard in both routes that can trigger one. Any system that can spend money on your behalf should be able to tell you afterwards exactly what it spent and on what. Putting that in the data model, rather than in a log file, made the spend queryable alongside the records it produced.
Eighteen back office screens, no bespoke admin shell
The module also carries 18 back office screens: a daily queue, a funnel board, per person and per company views, a gating screen for scoring decisions, a signals view, a notifications view, an addresses view, a dashboard and the rest. None of them required an admin shell of our own. They are built on the platform's own page shell, data table and form components, with a few small hand written tables inside detail views, and that is how the whole module stops at 247 files.
The numbers the system carries
All figures below were measured on 9 October 2026 through the command line interface over the application's own API. Every one of them is reproducible by re-running the command, and each command is listed in the source ledger beside this article.
People, companies and the event ledger
The database holds 6,698 people and 3,374 companies. Of the people, 5,068 carry a public LinkedIn address and 1,630 do not. The event ledger holds 5,249 events spread across 2,658 people, which means a little under half the people in the system have been touched at all. The other 4,040 are sourced and waiting, and the system says so plainly, which keeps the pipeline figure honest.
The active pipeline is 778 people. Sixty actions are overdue or due today. Forty-seven companies are carrying more than one live thread at the same time, which is the kind of collision that a flat contact list hides and a person-to-company link surfaces.
Outbound, reported the pessimistic way
On outbound, over the eleven weeks between the first invitation on 20 July 2026 and the reading on 9 October: 442 invitations sent, 181 accepted, 57 first messages, 27 follow-ups, 10 replies, 3 of them positive, and one booked conversation. The accept rate is reported as 28.1 per cent and it is deliberately the pessimistic reading, because it counts only accepts that can be matched to a logged invitation for the same person. Fifty-seven accepts have no matching invitation row, which is a gap in historical logging and not a gap in performance. The report shows both figures instead of picking the flattering one.
By stage: 5,474 discovered, 488 gated, 234 withdrawn, 179 rejected, 111 connected, 62 invited, 56 approved, 40 in dialogue.
Scoring coverage and verdicts
Scoring covers 1,719 companies and 6,268 people.
- Strong — 242 companies, 146 people.
- Maybe — 131 companies, 313 people.
- No — 189 companies, 1,231 people.
- Pending — 1,157 companies, 4,578 people.
That pending count is large on purpose. A verdict is only issued when the evidence covers enough of the profile, so "pending" means the system is telling us it does not know yet. We would rather read that than read a confident score built on three facts.
One divergence we have not closed
This belongs in the section with the numbers. The in-application dashboard and the command line read have disagreed on the headline people count, 6,019 against 6,034 when they were last compared side by side. That is a definitional question about which rows the dashboard counts, and it is still open. Every number in this article comes from the command line read.
The two pieces we wrote ourselves
The scoring engine sits outside the module and runs as a script against the platform's API, reading rules and facts, computing verdicts and writing evaluations back. We kept it there because the rules change weekly while the data model does not, and because a scoring pass over several thousand subjects runs as a batch job with its own timing. The platform holds the state and the audit trail, and the engine is a client of it like anything else.
The second piece is undo on our own records. The platform's audit log records a before and after snapshot for every write, and undo is registered per module, by handlers a module declares for itself. Ours do not declare them yet, so we wrote a narrow version for the one action that gets clicked a hundred times a week. One endpoint reverses one ledger event, named by its identifier rather than "the last one", and only for an invitation sent with a single click and no note. It writes the undo as a note, then deletes the event, then restores the lifecycle stage the original write stored, so the worst outcome of a crash is a visible note about an undo that did not happen. Withdrawals and anything else with a final effect are refused, and those have to be corrected from the command line.
Treat the platform as a foundation you extend, and you will size the work correctly.
What this means if you are evaluating Open Mercato outside commerce
What made this work was custom entities with real fields, an audit trail that comes for free, access control expressed per feature, and a component layer good enough that eighteen internal screens did not turn into a frontend project. None of those four is a commerce feature.
If your problem looks like ours, meaning a domain model with more than three record types, relationships that carry their own meaning, and a need to keep a record of what changed, then the platform gives you the boring 80 per cent and leaves you the part that is actually yours. Our 20 per cent came to 247 files and 14 entity types.
If your problem is a task tracker for ten people, the platform's own documentation tells you to use something smaller, and that advice is good.
A ten-minute check you can run yourself
You can verify the platform half of this without talking to anyone. Clone the repository, check out the release tag instead of the default branch, and list packages/core/src/modules. The module count is visible from that listing alone, and the licence each module declares sits one level down, in its own index.ts. Doing that is how we arrived at every Open Mercato figure in this article, and it is a better evidence base than any product page, ours included.
We are a certified Open Mercato partner and an open source contributor, and this system is what we point at when someone asks what the platform does once you take it out of a shop. It is ours, it is in production, and the numbers above are the real ones.
One boundary, stated plainly so nobody has to guess at it. This is our own internal system, built by us for us. It is not a client delivery and nothing here describes work done for a named customer.
Frequently asked questions
Can you build a custom application on Open Mercato that is not a shop?
Yes. The custom entities module lets you declare your own record types with their own fields and get forms, lists and an API without touching core code. Our outbound sales system is 14 entity types and 18 back office screens on top of the platform, in one module of 247 TypeScript files.
What do you get from the platform before you write any code?
Authentication and sessions, role based access expressed as features, multi-tenancy with queries scoped automatically, an audit log carrying a before and after snapshot with the actor, custom entities, and a component layer for data tables and forms. On the v0.9.0 release tag of 9 October 2026 the core carries 48 modules with 40 supporting packages around them.
How much custom code did your own system take?
One module, 247 TypeScript and TSX files, declaring 14 entity types with 145 field definitions between them, plus 18 back office screens. Four customer record types came from the core and were taken as they are.
What did you have to write yourselves?
Two pieces beyond the 14 entity types and the screens. The scoring engine runs outside the module as a script against the platform's API, because the rules change weekly and a pass over several thousand subjects is a batch job. And undo on our own records, because undo is registered per module and ours do not declare handlers yet, so we wrote one endpoint that reverses a single logged invitation.
How is this different from running the CRM module as it ships?
The CRM module covers companies, people, deals and activities, and we wrote up what it gives you on day one separately. This article is about the layer above that: record types the standard model has no place for, a scoring engine, and an event ledger, declared as custom entities on the same platform. If you are weighing the platform against a licensed suite, we went through that comparison row by row in Open Mercato and Salesforce.
Why not buy an outbound tool?
We wanted the scoring evidence to be a first class record with its own history and its own audit trail, and we wanted to own the system we run our own sales on. Our earlier engineer's read of the AI-native CRM category explains why we are careful about buying a finished product on that promise.
Sources
- Our own Open Mercato instance, read through the command line interface over the application's API on 9 October 2026. Every figure about the funnel has a command in the source ledger beside this article.
- The source of the module we wrote, counted with
findandgrepon 9 October 2026 and re-counted on 12 October 2026, after four screens had been removed from it. - Open Mercato release artefacts, measured on git tags rather than taken from marketing copy:
git ls-tree v0.7.0(released 26 August 2026),git ls-tree v0.8.0(released 18 September 2026) andgit ls-tree v0.9.0(released 9 October 2026). - thegoodcode, How to Run Your CRM on Open Mercato
- thegoodcode, The Data Model Decides Whether Your Systems Can Integrate
- thegoodcode, Open Mercato vs Salesforce
- thegoodcode, AI-Native CRM Systems: What the Data Says and How the Options Compare
