projects experience blog contact
← back to blog

What agency integration work taught me about systems design

Before I started building my own products, I spent two years at Four13 Group building integration systems for US e-commerce clients. It was the best education in systems design I could have asked for.

Every system lies about its API

The first thing you learn in integration work is that API documentation is aspirational fiction. Acumatica says a field is required — it’s not, but only for certain entity types. Shopify’s pagination says it returns 250 items — it returns 249 sometimes, and the cursor breaks if you don’t handle that. BigCommerce’s webhook payload format changes subtly between API versions without a changelog entry.

You learn to never trust the happy path. You build adapters that normalize chaos into something your system can reason about. And you test with production data, not fixtures, because the fixtures were written by someone who read the same aspirational documentation.

Idempotency isn’t optional

When you’re syncing data between two systems, things fail. API rate limits hit. Network connections drop. Servers restart. The question isn’t whether your pipeline will fail — it’s whether it’ll recover gracefully when it does.

Every operation needs to be idempotent. Every batch needs to be resumable. Every record needs a clear “last synced” state. I learned this the hard way after a pricing sync ran twice and overwrote a client’s carefully configured volume discounts.

Inngest’s durable execution model was a revelation for me. Write your pipeline as step functions, and the infrastructure handles retry and resume. No more hand-rolling state machines for every ETL job.

The adapter pattern saves lives

When you integrate N sources with M targets, you can either build N x M point-to-point integrations, or you can build N source adapters and M target adapters with a shared intermediate schema.

The math is obvious: N + M is always less than N x M. But the real benefit is cognitive. When you add a new platform, you only need to understand one interface, not every other platform in the system.

I used this pattern for the migration app I built at Four13. It connects Acumatica, Cin7, Shopify, and BigCommerce — any source to any target. Adding a fifth platform would require one adapter, not eight new integration paths.

Data loss is the only unrecoverable failure

Bugs can be fixed. Performance can be optimized. Bad UX can be redesigned. But if you lose someone’s data, that trust is gone.

In integration work, this means every record transformation needs an audit trail. Every sync needs to be dry-runnable. Every destructive operation needs a confirmation step. When the system handles 90,000+ records per migration, “we can just re-run it” is not an acceptable recovery strategy.

What I carry forward

These lessons — defensive design, idempotent operations, adapter patterns, audit trails — aren’t specific to integration work. They’re the foundations of any system that needs to be reliable.

I think about them every day as I build Paagos. The accounting data I’m handling is even more sensitive than e-commerce pricing. The stakes are higher. And I’m grateful I learned these lessons on someone else’s dime before applying them to my own products.