Skip to content
megapromotingLet's talk

Expertise · CRM and sales

A system where it is clear who was reached, through which channel, and what comes next.

We build the commercial system of an organisation: organisations and contacts, a stage path, the channels that bring data in by themselves — call, email, form, voice agent — and the brakes that stop sends before they become a problem. We do not sell our CRM; we build one for how you work.

Already builtTwo in-house implementations, in production, cited below. (1) MEGA CRM — the system our team uses to keep its own commercial activity: `server.js` has 9,516 lines and 99 HTTP routes, the repository contains 96 SQL migrations and around 95,000 lines of TypeScript in the interface, and the last commit is from 18 August 2026. (2) The CRM connectors in the Kallina platform: 12 server functions for amoCRM, 4 for Bitrix24, plus a documented OAuth flow for Zoho CRM and 10 functions for Google Sheets. The point that matters: **MEGA CRM is not for sale.** We show it as proof of workmanship, not as a product — it does not have strict data isolation between clients and it does not have an installation flow that does not require access to the server. The service is “we build a system like this for you”, not “we give you a licence for ours”.

Most companies do not have a CRM problem, they have a record-keeping problem: it is not clear who was contacted, through which channel, what was said and what comes next. A ready-made tool solves that when your work resembles the work the tool was designed for. When it does not — because you work with public administrations and private companies at the same time, or because half of the touchpoints come from a voice agent — you end up forcing the tool, and the team keeps the truth in a separate file. Then it is worth building something.

The system we show as proof is the one we work with ourselves. It is structured on separate projects, each with its own organisation type and field schema, so that the same application works both for a town hall and for a private company, without new columns in the database for each new type. Under the organisation sit the contacts, above it sit the campaigns. A lead moves through a route of seven stages, from “uncontacted” to “contract signed”, and can be reached through nine different channels, from the voice agent’s call to a visit.

The hard part, and the one that is learnt the hard way, is not sending. It is stopping. The system has working hours written in code, exclusion lists, deduplication by the address written in lower case — not by organisation —, a cooling period between campaigns, a daily cap shared between campaigns, and a switch that refuses to start the orchestrator, with no way round it. Each of these was added after it was missed once. We list them not as a feature list, but as a list of lessons.

The second thing we build almost every time is automation. A CRM in which data are entered by hand is emptied in three weeks. With us, the voice agent’s call is written automatically to the organisation record, with transcript and summary, and moves the lead further along the route if the call result justifies it. Replies to emails are collected from the mailbox every ten minutes and linked to the sending that triggered them. Opens and clicks are tracked separately. The person intervenes to decide, not to enter data.

Spam prevention in CRM — requests worth following up · video in Romanian, with subtitles and a transcript in English

Full transcription

Hello! In today’s analysis, we’re dissecting a problem that absolutely any business that wants to scale ends up running into at some point. How exactly do we automate commercial prospecting without everything turning into annoying, aggressive spam? We want to grow, we want to streamline things, clearly. But today we’re looking under the bonnet of a fascinating technical material to see how spam is prevented through exactly 6 clear, ring-based mechanisms, integrated into a truly secure ceramic system. It’s not just about the standard settings we tick and forget about, but about real architectures, facts and figures. Let’s get into the data! Well, in short, here’s the structure of our discussion. We start with the problem of acceleration without brakes, then we analyse a case study, the incident with the 42 messages, move on to the core of the analysis, meaning the 6 protection mechanisms, talk about the correct handling of unsubscribes, and finish with the classic dilemma: when is it worth building a system and when is it better to buy one.

Let’s begin! So, the essential question we start out with is this. How do we make sure the automation we implement doesn’t simply become spam? There’s an incredibly fine line here. The intention behind it is always good: we want to contact people, generate sales, but if the system is left to accelerate blindly, without very strict technical checks coded directly into its structure, the impact on the brand can be disastrous. We reach section 1, acceleration without brakes. Let’s look at the fundamental problem of evidence in these automated systems. Think of it like a very powerful car, but without a braking system. When standard software does not line up with the daily reality of work, things go off the rails quickly.

For example, let’s say the team interacts both with public administrations and with private companies. Completely opposite decision-making structures, right? Their data simply does not fit into the same rigid fields in a generic CRM. And what happens in practice? People start keeping the truth separate, in Excel files or notes on the desk, while the main automation keeps running empty on wrong data. That just means chaos. And our source has an absolutely brilliant quote here, a brutal truth from the industry. A CRM in which data is written by hand is emptied in 3 weeks. It makes perfect sense. People get tired, mistakes happen, and morale drops. Salespeople need to build relationships, not be data-entry robots. Whether it’s an intelligent voice agent that transcribes calls automatically, or emails that synchronise themselves in the background every 10 minutes, the idea is clear.

Automatic data input is no longer a luxury. It is the mandatory foundation of any functioning system. We move on to section 2, the incident with the 42 messages. Let’s dissect the anatomy of a real failure. 42. It’s not just some random number, but a real story from a prospecting campaign that triggered a real technical overhaul. Can you imagine? A single mailbox received exactly 42 messages within a few hours, on the same day. Naturally, the technical team first thought: okay, it’s a bug, a banal loop in the code sending endlessly. But when they looked more closely in the database, the reality was much more complex than that. The explanation? The system had been set up to extract and send messages per organisation, not per email address.

So, from a logical point of view, the algorithm had done its job perfectly. It found 42 legally distinct companies. The problem, and it’s a reality we often see in the local market, was that all these 42 entities used exactly the same email address. Whether it was the parent company’s, or the same external accountant’s, who managed dozens of companies. The entities were unique on paper, but the final destination of the message was one and the same. And to put things into perspective, do you know how many real people, flesh and blood, were affected by this avalanche of messages? Just 11. 11 people who were managing these dozens of businesses. This incident proved one very clear thing.

Good intentions and code that looks correct at first glance are never enough. The database always has invisible links, and the system has to anticipate them. Which brings us to the most important part, section 3. The six protection mechanisms, meaning the brakes coded directly into the heart of the system. Here’s the solution. The source details a protection ring made up of six distinct mechanisms that check one another. 1. Setting strict working hours, between 8 and 18. Nobody wants a sales email on Sunday at 3 a.m. 2. Permanent exclusion lists, meaning blocking sensitive institutions, such as schools or embassies. 3. And this would have prevented the incident from earlier: mandatory deduplication on the lowercased email address, not on the company name.

4. A 5-day cooling-off period for any address contacted, so we avoid suffocating the audience. 5. Strict daily caps so as not to upset global anti-spam filters. And finally, the sixth mechanism, the panic button. Of all of them, this mechanism 6, meaning the kill switch, or emergency switch, is a real cornerstone. It was implemented exactly after that incident with the 42 messages. What is it, in fact? A simple variable which, if activated, simply forbids the central system from starting any more. No exceptions, no hidden override command in the code. Any serious automation architecture needs such a physical button, figuratively speaking, which absolutely anyone in management can press without knowing how to program. We move to the fourth section, proper handling of unsubscribes.

Because, pay attention, it means much more than a simple link placed at the end of the page. Once you’ve sent the message, if the person wants out of the database, the process has to be flawless and sealed off. The analysis shows us a solid three-step process. Step 1. One-click unsubscribe from the header, which is in line with the new global standards, such as RFC 8058. Step 2. A visual preference centre, where the person can choose what kind of message they no longer want. But step 3 is, in fact, the most critical, and the one where many systems fail. Complete deletion. That does not mean ticking a box as inactive. It means deleting the address from, pay attention, 6 different database tables, plus putting it on a permanent blacklist.

Only then can you make sure that address does not reappear as if by magic at the next massive data import. And we are not talking just about technology. We are talking about respect and legal compliance directly in the email footer. Who are you? Who is the DPO officer? What is the exact legal basis on which you sent the message? And, most of all, from which public register did you initially extract the data? Our source underlines one golden rule. These legal bases must be rechecked at every legislative change. Why? Because you can have the most expensive system in the world. If, on the basis of a repealed law, you have turned technology into a major financial risk for the company.

We reach the last section, the fifth. When do you build vs. when do you buy? Let’s see the correct answer for a mature commercial infrastructure. The documentation addresses this decision in an extremely objective way. A ready-made, turnkey CRM is absolutely ideal. With one major condition. That your workflow fits perfectly with the logic designed by the platform creators. However, the decision to build a custom solution becomes the only way in three clear situations. When you interact with very different types of organisations, when you have a massive volume of automations in which manual work becomes impossible and, most importantly, when you have strict protection rules, such as those six mechanisms that off-the-shelf software simply cannot guarantee at such a deep level.

The good news? Building something safe in the back end does not mean throwing out the window the tools the team already knows. These protection mechanisms can run silently as an invisible layer of safety, while connecting to the usual interfaces. There are demonstrable architectures with connectors that run dozens of bidirectional functions with popular systems such as Amos ERM, Bitrix24, Zohos ERM or even the classic Google Sheets tables. In short, the security core remains intact, but the user experience is just as friendly. And so, the material leaves us with a rather uncomfortable point for reflection that is worth taking with us. Is a super advanced commercial system, which only the programmer who wrote it still knows how to shut down, really a super asset for the company or, in fact, an unacceptable risk?

At the end of the day, transparency, that emergency switch left in plain sight and clear documentation, are the things that set apart a simple blind machine from a truly scalable, professional and responsible business system. I hope this breakdown of the mechanisms brought a little more light to how proper automation should look. See you soon!

What it covers

The work, by component

Data enter the flow, with deduplication on three keys

A file of up to 50 MB is uploaded and processed in flow, in batches of 200 rows, so as not to exceed the database execution time, and progress is returned in real time, one line for each step. Before import, a deduplication index is built on three keys — fiscal code, email address and telephone number — and addresses are validated: format, disposable domains, invalid patterns. The same organisation does not enter twice under two differently written names.

Every touch is written to the organisation record

Nine communication channels, from the voice agent and human call to a visit, and a route of seven stages with real labels: uncontacted, contacted, reply received, offer sent, actively interested, negotiation, contract signed. Next to each stage, the percentage that should pass further on is written — not as a promise, but as a reference for whoever looks at the funnel and wants to know where it is being lost.

The voice agent’s call moves the lead by itself

When the agent finishes a call, the result enters the system via a webhook whose signature is checked: transcript, summary, sentiment, recording address, duration. The organisation is identified by telephone number, through a function written in the database for the formats in which numbers appear in real data, and the call is linked to its record. If the result is “interested” or “meeting scheduled”, the lead moves automatically along the route and its last contact date is updated.

Sending has brakes, not only acceleration

Working hours written in code: 08:00–18:00, Chişinău time zone, Monday to Saturday. Exclusion lists for schools, high schools, kindergartens, embassies and consulates. Deduplication by the address written in lower case — not by organisation, a distinction that matters enormously when several companies use the same mailbox. Five-day cooling between campaigns for the same address. Global daily cap, shared proportionally between campaigns, plus a per-run cap, so that sends are spread over several hours, not in a block.

A switch that cannot be bypassed

The campaign orchestrator checks an environment variable before anything else. If it is set, it refuses to start and exits — there is no command-line argument that overrides it, there is no “force”. It was added on 1 May 2026, after an incident of duplicate sends. A system that sends in your name needs a stop that someone who is not a programmer can press.

Unsubscribe in one click, in three steps

The first step is the standard one-click unsubscribe header, in line with RFC 8058 — the requirement that large email providers impose for bulk sends. The second is a preferences centre, where unsubscribing can also be reversed. The third is full deletion on request, which removes the address from six tables, adds it to a permanent block list and leaves a trace in the log. All three are protected with a token tied to the recipient, so that no one can unsubscribe someone else.

Replies and reactions are collected automatically

Replies to emails are read from the mailbox through Microsoft Graph, every ten minutes, and automatically linked to the sending that triggered them. Delivery status is synchronised from the sending provider. Opens are tracked with a pixel, clicks via redirect, and deliverability dashboards show the domains with problems. A separate service tracks the remaining credit with paid providers and sends an alert before it runs out — not after.

Search by what an organisation does, not only by what it is called

In addition to full-text search, the question is turned into a vector with an embedding model and matching is done in the database by a custom function, with an adjustable similarity threshold (default 0.25) and project-level limiting. Practically: “companies that do refrigerated transport” also finds organisations that do not have any of those words in their name.

Connection to the CRM you already have

If your team is already working in a CRM, we do not replace it by reflex. We have written and run the connector for amoCRM — 12 server functions, including the full OAuth flow, token refresh and state verification — plus Bitrix24 with OAuth and webhook, an OAuth guide for Zoho, and ten functions for Google Sheets, from reading a sheet structure to importing contacts.

What it looks like

The path, step by step.

01

First the model, then the interface

What is an organisation for you, what is a contact, what is an opportunity, which fields are mandatory and which are only useful. This discussion seems slow and it is the only one that cannot be recovered later: a wrong model is paid for in every report you ask for afterwards.

02

The route and stages, written as rules, not as habit

The stages a lead goes through, what moves it forward and what moves it back, who is responsible at each one. We also write the automated rules — which call outcome moves the lead up, which inactivity moves it down — because a route that moves only when someone remembers to press is not a route, it is a list.

03

The channels that bring data in by themselves

Calls from telephony or the voice agent, responses from the mailbox, forms on the site, webhooks from other systems. Each channel is connected and tested separately, and for each one we decide what happens with data that does not match anything in the database — because those are the ones that are lost silently.

04

Brakes before acceleration

Sending hours, exclusion lists, deduplication, cooling, thresholds, unsubscribe, emergency stop. We put them in before the first campaign, not after the first complaint. It is the part where our experience costs the least and is worth the most, because it is made of mistakes already paid for.

05

Handover: procedures, roles, documentation

Who has which role, how to add a person, how to stop a campaign, where to look when something has not gone out, what to do on a deletion request. A commercial system that only its builder knows how to stop is a risk, not an asset.

One centre. Around it, what enters it — along separate routes.THE CENTRE RELIES ON WHAT SURROUNDS IT
The channels converging on the same record: the voice agent call, the human call, email and the inbox reply, the website form, the webhook from another system — and the brakes that decide what goes back out.

The data

What we touch, where it lives, and how long it stays

The questions anyone with a data protection officer would ask — asked here before they do.

Where the data sits and how it is structured
PostgreSQL via Supabase, with 96 versioned migrations. The structure is hierarchical: projects, under them organisations with flexible fields in JSONB and a full-text search vector, under them contacts, and campaigns hang from the project. Each project defines its own field schema — that is why the same application serves both public administrations and private companies, without the database growing for every new type of organisation.
What is written in the footer of each email sent
The full identity of the company — name, tax code, registered office — the address of the data protection officer, the legal basis invoked and where the address comes from: public registers and public profiles, stated explicitly, not implied. Plus unsubscribe in one click and a fallback version, with a one-word reply. Anything relating to the legal basis is rechecked with every change in the law — a mass mailing that cites an out-of-date basis is a problem even if everything else is impeccable.
Who sees what
Access is through authentication, application routes are closed behind a gate, and the administration area has an extra gate. Roles are separated: administration, owner, sales, prospecting, and a distinct role for the automatic agent — because an agent that writes into the system should not have a human’s rights. There is no open registration.
What we explicitly check at installation
That every secret is actually set on the server: the secret used to sign incoming webhooks and the secret used to sign unsubscribe tokens. These are checks that seem formal until they are not: a signature check has nothing to compare if the secret is missing, and a predictable token is a token that protects no one. We put them on the handover list, not in assumptions.
What is deleted on request and what remains
A full deletion removes the address from six tables and puts it on a permanent block list, so that a later import does not bring it back. A trace remains in the log, with the reason — because you must be able to show, a year later, that the request was fulfilled. Statistical aggregates, which do not identify anyone, remain as well.

A case

One address received 42 emails in a day. It was not a loop.

The situation

In a prospecting campaign for organisations, a single mailbox received 42 messages on the same day. The first, convenient hypothesis is a loop in the code. It was not.

What we built

Recipient extraction was done per organisation, not per address. Forty-two organisations used the same mailbox — an absolutely common situation in the local business environment, where an accountant, a parent company or an administrator serves several entities. Each organisation was, correctly, a unique recipient; the address was not. The total number of people affected in that incident was 11. The fix was in three parts, not one: deduplication was moved to the address written in lowercase, a five-day cooling period between campaigns for the same address was introduced, and all sending scripts were required to go through a common protection module — the one that refuses to record a send without a campaign identifier. On the same day, the kill switch that stops the orchestrator completely, with no bypass route, was also added.

What came out

Today, address deduplication, the unsubscribe list, domain filters and the five-day cooling period are guarantees of the common module, not habits of the script that happens to run. A manually written script, hurriedly written, can no longer bypass the protections, because it is no longer allowed to send on its own.

What the case does not say

The lesson does not transfer automatically: every database has its own form of duplicate. In one it is the email address, in another it is the phone number of a group of companies, in a third it is a person with two roles. The first thing we do in a new import is look for what the duplicate form is there — we do not assume it is the same.

Questions

What people ask us before they call

Will you sell us the CRM you work with?

No, and the reason is technical, not commercial. Our system is tailored for a single team: it does not have strict data separation between clients and it does not have an installation flow that does not assume server access. To be handed over to someone else, those exact two things would have to be rewritten. We show it for the same reason a carpenter shows their workshop — it says more about the craft than a brochure. What we sell is building a system for the way you work.

Why would I build, instead of buying a ready-made CRM?

Most of the time you should not, and we tell you so. A ready-made tool is the right answer when your work resembles the hypothesis it was designed for. Building becomes justified in three concrete situations: you have fundamentally different organisation types that do not fit into the same set of fields; half of your touches come from automated systems that must write to the record on their own; or you need sending rules that the tool does not give you and that you cannot afford to break. If none of these applies, we tell you to buy.

Can you connect the system to the CRM we already use?

Yes. We have written and run the connector for amoCRM — 12 server functions, with the OAuth flow, token refresh, lead retrieval and status check — and for Bitrix24, with OAuth and webhook. For Zoho CRM we have the OAuth journey documented by data centre regions. And when the team’s real source of truth is a spreadsheet, we have ten functions for Google Sheets, from reading the sheet structure to importing and updating contacts.

How do calls get into the CRM, concretely?

Through a signed webhook sent at the end of the call. The system takes the phone number and looks up the organisation through a function written specifically for the formats in which numbers appear in real data — not by string comparison, which would miss half the cases. The call is saved with transcript, summary, sentiment, recording address and duration, linked to the record, and the rule in code can move the lead further along the route depending on the call result.

How do you make sure we do not end up sending spam?

Through six mechanisms that check one another, not through good intentions: sending hours, exclusion lists by institution type, deduplication by address written in lowercase, a five-day cooldown for the same address, daily and per-run limits, and a kill switch that stops the orchestrator with no bypass. Below is the concrete case that taught us why deduplication must be done by address, not by organisation.

What happens when someone asks not to be contacted anymore?

It has three stages, all protected with a token tied to the recipient. One-click unsubscribe, directly from the email header, in line with RFC 8058. A preference centre, where the decision can also be reversed. And complete deletion, which removes the address from six tables and adds it to a permanent block list — so that an import made six months later does not bring it back. The last part is the one most systems miss.

Where is the data stored and who can see it?

In a PostgreSQL database, on the infrastructure agreed at the start of the project, with versioned migrations — meaning every structural change is a file, not a manual intervention. Access is by separate roles, with a separate role for automated agents, because a system that writes to the database should not have human rights. There is no open registration and there is no public surface.

Can you import our old database, duplicates included?

Yes, and duplicates are exactly why the import is built this way. The file is processed as a stream, in batches of 200 rows, with a deduplication index on tax code, email and phone built before writing, plus address validation: format, disposable domains, invalid patterns. What does not match is not silently discarded — it is reported, so you can decide.

Can you guarantee a sales increase?

No. We can guarantee that you will know who was reached, through which channel, what was said and what comes next — and that the system stops itself when it should. The outcome figures depend on the offer, the market and the calling team, meaning on things we do not control. We do not publish improvement percentages we have not measured, neither for ourselves nor for anyone else.

What the statements above rest on (24 sources)

24 of them are code and files from our repositories. We don't publish their name or line: together, on a single page, they would describe too precisely how systems that aren't only ours are built. We go through them with you, in the repository, on request — verification stays possible, it just happens in a conversation.

What would you want to work better?

Tell us about your process. Together we decide what is worth building, what we can connect, and how we check the result.

Let's talk