Syncing Ostendo ERP with Pipedrive CRM: Building TurfDrive

When a landscaping and turf company approached us with a common problem—their sales team working in Pipedrive while their operations lived in Ostendo ERP—we knew we had to build a bridge. The result? T...

Syncing Ostendo ERP with Pipedrive CRM: Building TurfDrive

Syncing Ostendo ERP with Pipedrive CRM: Building TurfDrive

When a landscaping and turf company approached us with a common problem—their sales team working in Pipedrive while their operations lived in Ostendo ERP—we knew we had to build a bridge. The result? TurfDrive: a Rails application that keeps both systems in perfect sync.

The Challenge

Ostendo is a powerful manufacturing and distribution ERP system popular in Australia and New Zealand. It handles inventory, purchasing, manufacturing, and sales. But for modern sales teams, CRMs like Pipedrive offer a better experience for managing deals, tracking contacts, and forecasting revenue.

The problem: data silos.

Sales reps would close deals in Pipedrive, then someone had to manually re-enter that information into Ostendo to kick off fulfillment. Jobs created in Ostendo wouldn't appear in Pipedrive. Customer data would drift out of sync. It was a recipe for errors, delays, and frustrated staff.

The Solution: TurfDrive

TurfDrive is a Rails 8.1 application that sits between Ostendo and Pipedrive, syncing data bidirectionally in near real-time. Built with Ruby on Rails, SQLite, and Sidekiq, it's deployed via Kamal to a single server that runs 24/7.

What It Syncs

Jobs → Deals

When a project (called a "Job" in Ostendo) is created, TurfDrive pushes it to Pipedrive as a Deal. We support two deal types: "PT Sales" (project & turf supply) and "Supply Only" (turf-only orders). Each type flows into its own pipeline in Pipedrive with appropriate stages and values.

Customers → Organizations

Customer records sync both ways. When a sales rep creates a new organization in Pipedrive, it flows into Ostendo. When operations adds a customer in Ostendo, the sales team sees it in Pipedrive.

Sales Orders

Once a deal closes in Pipedrive, the associated sales order data syncs back to Ostendo, ensuring the warehouse and logistics teams have everything they need.

Status Tracking

Deals move through stages: Open → Won/Lost. We track status mismatches—if a deal is marked Won in Pipedrive but the Ostendo job is still Open, we flag it for review.

Architecture Decisions

Why Rails?

We chose Rails for its maturity, excellent background job support via Sidekiq, and ability to ship fast. This wasn't a greenfield product experiment—it was operational infrastructure that needed to work reliably from day one.

Why SQLite?

For a single-server deployment handling moderate sync volumes, SQLite is perfect. No database server to manage, blazing fast reads and writes, and dead-simple backups. Rails 8's Solid Queue runs on SQLite too, so we get background jobs without Redis.

Why Kamal?

Kamal (from the Rails team) makes zero-downtime deploys trivial. We containerize the app, push to the server, and Kamal handles the rest. No Kubernetes complexity, no orchestration overhead.

Technical Highlights

Bidirectional Sync Logic

The trickiest part of any integration is conflict resolution. What happens when both systems update the same record?

We use a "last write wins" strategy with conflict detection:

  1. Each sync operation stores a timestamp
  2. If both systems modified a record since the last sync, we flag it as a conflict
  3. The sync proceeds using Pipedrive as the source of truth for deals, Ostendo for jobs
  4. Admins review conflicts via a dashboard

Error Handling

Network hiccups, API rate limits, and validation failures are inevitable. We built robust error handling:

  • Exponential backoff for retries (1min, 5min, 15min, 1hr)
  • Error categorization: transient (retry), validation (skip), fatal (alert)
  • Sync status tracking: pending, synced, error, skipped
  • Daily error digest emails so the team knows what needs attention

Data Integrity

We run nightly data integrity checks:

  • Deals in Pipedrive but missing from Ostendo
  • Jobs in Ostendo not synced to Pipedrive
  • Status mismatches (Won deal, Open job)
  • Orphaned records

These checks feed into automated reports and Slack alerts.

Performance

We process thousands of records daily. To keep things fast:

  • Batch processing: Sync in batches of 100, not one-by-one
  • Selective sync: Only sync records modified since the last run
  • Background jobs: All heavy lifting runs async via Sidekiq
  • Caching: Customer and job type lookups are cached in Redis

Lessons Learned

1. API Rate Limits Are Real

Pipedrive's API has generous rate limits, but when you're syncing thousands of deals, you hit them. We added rate limit detection and automatic backoff. The sync slows down temporarily, but it never fails.

2. ERP APIs Are… Special

Ostendo's API is SOAP-based (yes, really). We wrapped it in a Ruby client that handles authentication, error parsing, and XML-to-Ruby conversion. Not glamorous, but it works.

3. Idempotency Matters

Network requests fail. Jobs retry. We made every sync operation idempotent—running it twice produces the same result as running it once. This required careful use of unique identifiers and "upsert" logic.

4. Observability Is Critical

We log every sync operation with structured data (JSON). When something goes wrong, we can trace exactly what happened. Tools like Sentry catch exceptions, but logs tell the full story.

The Result

TurfDrive has been running in production for over a year. The sales team works exclusively in Pipedrive. The operations team works in Ostendo. And the data stays in sync, automatically, with minimal intervention.

Metrics:
- ~5,000 deals synced since launch
- 99.8% sync success rate
- Average sync time: 2 minutes (from Ostendo update to Pipedrive)
- Zero manual data entry between systems

Takeaways for Similar Integrations

If you're building an ERP ↔ CRM integration:

  1. Understand the data model deeply before writing code. Spend time with users to see how they actually work.
  2. Start with one-way sync, then add bidirectional once you've proven the basics.
  3. Build observability from day one. You can't debug what you can't see.
  4. Handle errors gracefully. Transient failures shouldn't break the sync.
  5. Keep it simple. We didn't need Kafka or event streaming—Sidekiq and polling work great at this scale.

Want Help with Your Integration?

We build custom integrations, API wrappers, and sync systems for businesses that need their tools to talk to each other. Whether it's ERP, CRM, e-commerce, or something else entirely, we can help.

Get in touch and let's talk about your integration challenges.


TurfDrive is built with Ruby on Rails 8.1, SQLite, Sidekiq, and Kamal. Deployed on a single Ubuntu server. No Kubernetes, no microservices, no complexity—just reliable software that works.