Skip to main content
Most partner integrations against Raise are fundamentally about moving data — out of Raise into something else, occasionally from something else into Raise, sometimes both. The architecture of that movement determines whether the integration scales, handles failures gracefully, recovers from outages, and produces a reliable picture downstream. This page covers the five common sync architecture patterns, when each is the right fit, and the trade-offs between them. The audience is partner integration architects designing or auditing a Raise integration’s high-level structure.

The fundamental shape

For most partner integrations, Raise is the source and an external system is the destination: The customer’s fundraising team operates Raise (collecting donations, managing donors, configuring campaigns). The customer’s other teams need that data in their respective systems. The partner integration’s job is to keep those downstream systems aligned with what’s happening in Raise. The patterns on this page describe different ways to design that pipeline. Most production integrations use a combination of two or three.

Pattern 1: webhook-driven push (the default)

The simplest pattern — Raise pushes events to the partner, the partner writes to the destination. The pattern in code:
JavaScript

When this pattern fits

For most partner integrations, this is the default pattern. Start here unless something specific rules it out.

When this pattern doesn’t fit alone

Webhook-driven push alone is rarely a complete solution. It typically pairs with reconciliation (pattern 4) and backfill (pattern 5).

Pattern 2: polled pull

For destinations that can’t receive webhooks (legacy systems, on-premise tools, batch-oriented warehouses), the partner integration polls Raise on a schedule: The pattern in code:
JavaScript

When polled pull fits

Trade-offs vs. webhook-driven

Polled pull misses deletions if the destination doesn’t track its own state — a record that exists in the destination but no longer in Raise won’t be detected by a “give me everything modified since X” query. For destinations that need delete-handling, use webhooks or pair polling with a periodic full inventory comparison.

Advancing the checkpoint correctly

A common bug in polled pull: advancing the checkpoint to “now” rather than to the last successful record’s timestamp:
JavaScript
Always anchor the checkpoint to a record’s actual timestamp, not to wall-clock time. The slight overlap on the next poll (re-fetching the boundary record) is fine — idempotency in the worker handles it.

Pattern 3: hybrid (webhook + periodic reconciliation)

The most robust production pattern. Webhooks handle steady-state real-time sync; periodic reconciliation catches anything webhooks missed. The reconciler runs daily (or hourly for higher-stakes integrations) and verifies that every Raise record from yesterday made it to the destination. Gaps go back into the queue for re-processing. The pattern in code:
JavaScript

Why hybrid is the production default

Webhooks are reliable for ~99.5% of events. Reconciliation closes the gap to ~100%. For partner integrations where data accuracy matters (and it almost always does), the hybrid pattern is worth the extra complexity.

Tuning reconciliation cadence

Daily reconciliation is the right default. Move to hourly only if the integration’s SLA genuinely requires it.

Pattern 4: backfill + steady-state

For customers with existing data when the integration starts, a backfill pulls historical records before steady-state sync takes over. The full sequence:
1

Customer onboarding triggers initial backfill

Pull historical records via POST /api/Gift/query with pagination.
2

Subscribe to webhooks (in parallel)

Set up the webhook subscription early so events fire to a queue from the start.
3

Backfill streams records to the same queue as the webhook

Both backfill and live events flow through one worker — single processing path.
4

When backfill completes, mark the customer as live

The queue continues to drain, now fed only by webhooks.
5

Daily reconciliation begins after cutover

Reconciliation verifies steady-state sync correctness over time.
Critical detail: both backfill and steady-state events go through the same queue and worker. Having separate backfill and live paths creates drift in edge-case handling. See Sync Raise Gifts to an External System: The same queue for backfill and steady-state.

When backfill is needed

Backfill performance

A customer with 100,000 historical gifts is a substantial backfill — at Take=1000 with 1-second throttling, that’s ~100 minutes of constant API calls. Plan for this:
JavaScript
For very large backfills, consider running in parallel across multiple workers — each handling a non-overlapping ID range — to reduce wall-clock time.

Resumable backfill

If the backfill crashes partway through, it should resume from where it left off rather than starting over. Track progress in a checkpoint:
JavaScript
Resumability turns a multi-hour backfill from a single fragile operation into one that can fail and restart without losing progress.

Pattern 5: two-way coordination (rare)

When the partner integration writes back to Raise — for example, syncing donor preferences from an external system into Raise — coordination between the two directions becomes important. The pattern in code:
JavaScript

The echo problem

When the partner writes to Raise, Raise fires a webhook back. Without coordination, the partner integration would treat the echo as an external change and try to sync it back to the external system — producing a loop. The “write attribution” pattern records the partner’s intent before writing so the echo can be recognized and ignored.

When two-way sync is needed

Most integrations are one-way out of Raise. Two-way is the exception. When you do need it, plan the echo-handling explicitly.

Combining patterns

Real production integrations combine these patterns. The most common combination: For destinations that can’t receive webhooks: For partner integrations with bidirectional needs: The combination matters more than any single pattern. A partner integration with all three (backfill, steady-state, reconciliation) handles 99%+ of customers’ production needs.

Destination-specific considerations

The patterns above apply broadly, but specific destination types have particular needs:

Accounting destinations (QuickBooks, Xero, NetSuite)

BI / data warehouse destinations (Snowflake, BigQuery, Redshift)

External CRM destinations (HubSpot, Salesforce, ActiveCampaign)

Marketing automation destinations (Mailchimp, Klaviyo, Iterable)

For each destination type, the partner integration’s architect should review the destination’s specific constraints and adapt the patterns above to fit.

Operational practices

A few practices that apply to any sync architecture:

Monitor everything end-to-end

Track the full journey: gift creation in Raise → webhook delivery → queue depth → worker processing → destination write → reconciliation verification. Latency at each step. Failure rate at each step. The end-to-end view catches issues that any single stage’s metrics miss.

Per-customer dashboards

For partner integrations with many customers, build per-customer dashboards that show sync health for each:
  • Last successful sync timestamp
  • Records synced today / this week / this month
  • Open dead-letter entries
  • Webhook subscription status
  • Recent reconciliation results
A customer asking “is our integration working?” should be answerable in seconds, not hours.

Customer-facing audit trail

Expose the sync history to the customer’s team. They should be able to look up any Raise gift ID and see where it is in the sync pipeline — synced to which destinations, with what destination ID, at what time. Turns “we’ll have to investigate” into “I can see exactly what happened.”

Graceful degradation

When a destination is unavailable, the sync should pause for that destination rather than failing the whole pipeline. A workflow that writes to three destinations should continue to write to the two that are healthy when the third is down.
JavaScript
The customer’s BI dashboard being down shouldn’t prevent the customer’s accounting from being up-to-date.

Choosing an architecture

For a new integration, walk through these questions:
1

Where does the data flow?

Out of Raise (most common), into Raise, or both?
2

What's the acceptable latency?

Seconds → webhook-driven. Minutes → either webhook or polled. Hours → polled is fine.
3

Can the partner host a public webhook receiver?

Yes → webhook-driven preferred. No → polled.
4

Is there existing data to backfill?

Yes → backfill + steady-state pattern.
5

How critical is data accuracy?

High → add reconciliation as a backstop. Low → steady-state alone may suffice.
6

Are there multiple destinations?

Yes → fan-out from one worker to each destination, with independent failure handling.
7

Is bidirectional sync needed?

Yes → plan the echo-handling and write attribution explicitly. No → simpler architecture.
The answers map directly to the patterns. Most integrations land on backfill + webhook-driven push + daily reconciliation — the production-default combination that handles the largest share of real-world needs.

Where to go next

Sync Raise Gifts to an External System

The end-to-end recipe that combines several of these patterns for a real implementation.

Reconcile with CRM+

The reconciliation workflow that the hybrid pattern depends on.

Error Recovery Patterns

The error-handling patterns that the sync worker uses for resilience.

API Performance Tips

The performance patterns that make sync workloads efficient.
Last modified on May 21, 2026