The most expensive sentence in integration projects is a short one: "and everything should be real-time."
We hear it on nearly every first call about connecting an ERP or CRM to custom software. It sounds like rigor. It is actually a price multiplier, because real-time everything means every screen in your new application depends, synchronously, on a system that was never built to answer that many questions. When the ERP slows down, your product slows down. When the vendor takes it offline on a Sunday, your product goes offline with it. We run systems integration work for German mid-market companies and beyond, with German project leadership and a senior engineering team in Pakistan, and the first thing we do in scoping is take that sentence apart field by field. Most of it survives as "fresh enough". Very little of it is genuinely real-time.
What real-time actually costs
A live query against the ERP looks simple in a demo and compounds in production. Your application's availability becomes the minimum of two systems' availability. Vendor maintenance windows become your maintenance windows. Rate limits and volume pricing vary by ERP, and we have been bitten by both, so a busy month in your product can become a line item on a vendor invoice; the selected ERP's limits are one of the first things we check in scoping. And every test run needs the other system to be awake and cooperative, which slows down the team building your product long after the integration ships.
None of this appears in the estimate that sold "real-time". It appears in month four, when the project that was supposed to take weeks is still going, and the reason given is always the same: the other system. We have been brought in to finish integrations that started this way, and the rescue is usually the same too. Cut the synchronous coupling, keep the two or three flows that truly need it, rebuild the rest as copies.
The pattern we start from: the read-model
Our default architecture is a read-model. Your application keeps its own copy of the data it displays, shaped for its own screens, refreshed from the system of record on a schedule or by events. The ERP remains the source of truth for writes. Your app reads from its own store, so it can answer from its local copy without waiting on the ERP, it survives the ERP being down, and it can join data the ERP keeps apart, like customer, open orders, and payment status on one screen, without hammering the vendor's API on every page load.
Martin Fowler's write-up of CQRS makes the underlying point well: the model you read with does not have to be the model you write with. Integration work is where that idea pays for itself fastest.
The trade-off, stated plainly, is staleness plus a pipeline you now own. Staleness is manageable: you decide per field how old the data may be, and you surface that decision in the UI where it matters. The pipeline is the real cost. Someone has to own the sync, watch it fail, and fix it when the ERP changes under it. Budget for that ownership from day one or the read-model quietly rots.
Where events earn their keep
Event-driven sync is the right tool exactly where a change in one system must cause an action in another. An invoice marked paid in the ERP triggers provisioning in your product. An order released in the CRM triggers fulfilment. These are flows, not displays, and they deserve events: webhooks or a message queue, consumed idempotently and retried on failure.
The mistake we see is applying that machinery to data that only ever gets read. Event infrastructure for a price list that changes twice a month is a cron job wearing a costume.
When a nightly batch is genuinely fine
Batch has a bad reputation with people who have never had to operate real-time plumbing. Here is the honest test: what does the business lose if this number is four hours old? For product catalogs, price lists, reporting aggregates, and the export your accountant picks up at month-end, the answer is nothing, and a nightly export with a diff and a reconciliation report is boring and correct. For inventory promised to a customer at checkout, the answer is money, and batch is wrong.
Do that arithmetic per field, in writing, during scoping. It is the single cheapest hour in the whole project, and it is the difference between an integration that ships in a quarter and one that ships in a year.
The German specifics: DATEV, XRechnung, and where the data lives
Three things come up in almost every integration we scope for a German client, and they change the design.
DATEV first. If your custom software sends invoices, your Steuerberater will want the booking data in DATEV format at month-end, and this is usually the first integration the accounting side demands. It is a file export with a strict specification, which makes batch the literally correct pattern here. Teams that overbuild this as a live sync have spent real money making an accountant's monthly import more complicated.
XRechnung second. Since 2025, German businesses must be able to receive B2B e-invoices, with the obligation to issue them phasing in through 2028, per the Koordinierungsstelle für IT-Standards. If your ERP or invoicing software touches German B2B, receiving and parsing e-invoices is an integration requirement on a legal deadline, not a backlog item. The same office maintains the XRechnung specification itself. We treat this as table stakes in any invoicing-adjacent scope now.
Data residency third. Under DSGVO, where your read-model physically lives and who can access the sync pipeline are questions your legal counsel and your customers will both ask. We run these workloads in EU regions by default and keep the synced copy to the fields the application actually displays. Copying the entire customer record into a second database because it was easier than selecting columns is a privacy problem you created for yourself.
On capability: the invoicing product in our QuickBilling case study shipped its REST API, webhooks across 30-plus event types, a sandbox environment, and idempotency keys before the UI was finished, because a billing product exists to sit inside other people's accounting workflows. That is what "built for integration" looks like in practice, and it is the standard we build to when we are on the other side of the wire too.
Testing is where integration projects live or die
Integration code is easy. Integration trust is the deliverable, and it comes from three habits we apply on every engagement.
Sandbox first, with your eyes open. Every build starts against the vendor's sandbox rather than production. Know that sandboxes lie: they run older data, looser rate limits, and none of the weird records that fifteen years of real business produced. Sandbox is where you learn the API. It is not where you learn whether the integration works.
Idempotency everywhere. Many providers, Stripe among them, document at-least-once webhook delivery, which means your consumer will receive the same event twice and must shrug; each vendor's docs are worth checking before you assume otherwise. Stripe's documentation on idempotent requests is the clearest public statement of the discipline, and we hold our own webhooks to it: dedupe keys on receipt, unique constraints in the database, and a test that fires the same event repeatedly and checks it is processed once.
Replay as a first-class feature. Every event and every batch run gets logged so you can re-run it. The day the ERP vendor renames a field without telling anyone, replay is the difference between an afternoon of re-processing and a week of manual reconciliation. Teams that skip the log learn why it existed at the worst possible moment.
What the first two weeks look like
When we scope an integration, the first two weeks produce no integration code. They produce a field inventory of every screen the new application needs, a freshness budget for each field, and a failure-mode map of what happens when each system is down or feeding you garbage. From there the architecture mostly falls out: read-model for the displays, events for the handful of flows that trigger actions, batch for the accountant and the catalog.
If the scoping reveals that the ERP itself is the problem, that is a different decision, and our rebuild, refactor, or wrap guide walks through how we make it. If the verdict is that your aging system mostly works and needs a modern surface, that is exactly what our product modernization engagements are for. And if you have an integration that has been "nearly done" for six months, send us the field list. We will tell you which two fields actually need real-time. It is rarely more than two.
Frequently asked questions
Do we really need real-time sync between our ERP and our customer portal?
Almost never, and this question comes up on nearly every first call we take. What you usually need is freshness you can state in numbers, using the kind of planning values we write down in scoping: inventory accurate within a minute, prices within a day, invoice status within an hour. Each of those has a cheap pattern behind it. Real-time means your portal goes down whenever the ERP does, and that coupling is what you are actually buying.
How long does an ERP or CRM integration take?
As a planning assumption from our engagements: a read-model plus one event flow against a documented API runs six to ten weeks, including testing. Add a second system or an undocumented legacy interface and it grows from there. The schedule is driven less by our code than by vendor sandbox quality and how fast the ERP side answers questions, so we price discovery first.
Should we modernize the ERP before integrating it with new software?
Usually no. Wrap it behind a clean API, integrate against that, and let the system keep earning. The rebuild-versus-modernize decision is its own question with its own criteria, and we wrote a separate decision guide for it. Our planning heuristic: starting a modernization program because you need one integration is how a ten-week job becomes a two-year one.
Can you connect our invoicing to DATEV for our Steuerberater?
Yes. DATEV export for the accountant is one of the most common integration requests we get from German clients, and it is a batch file with a strict format, which makes it a good first deliverable. We also handle XRechnung receiving and the surrounding e-invoice obligations, and we can scope both inside a normal integration engagement.