Mobile Sales API offline sync fails with 504 Gateway Timeout, unsynced records lost after reconnect

Our field sales team is experiencing critical sync failures with the Mobile Sales API. When reps work offline and accumulate updates (opportunities, contacts, notes), the sync process consistently fails with 504 Gateway Timeout errors after about 45 seconds.

The mobile app’s local cache appears to be working correctly - data is stored locally and queued for sync. However, when the device reconnects and attempts to push changes, we get:


HTTP 504 Gateway Timeout
Sync endpoint: /crm/v2/mobile/sync/batch
Payload size: ~2.3MB (150+ records)

Our retry logic attempts 3 times with exponential backoff, but all attempts fail. The offline data then gets stuck in limbo - not synced but not discarded either. Sales reps are losing confidence in the mobile app because their work isn’t reliably reaching the server. We’ve tested with smaller batches (20-30 records) and those succeed, but that’s not practical for reps who spend days in the field.

Is there a way to configure the sync timeout threshold or implement chunked uploads? How should we handle the retry logic when dealing with large offline datasets?

Have you considered implementing incremental sync instead of batch sync? Our mobile team switched to a continuous sync model where records are pushed to the server as soon as connectivity is detected, rather than waiting for a manual sync action. We use a background service that monitors network state and processes the local cache in real-time with small batches (10-15 records at a time). This eliminated the large batch problem entirely. The trade-off is more API calls, but the reliability improvement was worth it for our field teams.

Your offline sync architecture needs restructuring based on what you’ve described. Here’s a comprehensive solution addressing all three critical areas:

Offline Sync Handling - Chunked Upload Strategy: Implement a multi-tier sync approach in your mobile app. When the sync process starts, analyze the local cache and dynamically determine batch sizes based on record complexity and payload size estimation. Use this logic:

// Adaptive batch sizing
if (totalRecords > 100) {
  batchSize = 25; // Conservative for large queues
} else if (payloadSize > 1MB) {
  batchSize = 30; // Size-based limiting
} else {
  batchSize = 50; // Standard batch
}

504 Error Retry Logic - Progressive Degradation: Your current retry logic is too simplistic. Implement a progressive strategy:

  1. First attempt: Send full batch (or calculated chunk size)
  2. If 504 occurs: Split batch in half, retry each half
  3. If still failing: Reduce to micro-batches of 10 records
  4. Track failure patterns - if specific records consistently fail, quarantine them for manual review

Implement a circuit breaker pattern to prevent overwhelming the API when experiencing persistent failures. After 3 consecutive batch failures, switch to micro-batch mode automatically.

Mobile App Local Cache - State Management: The critical missing piece is granular sync state tracking. Your local cache should maintain these states per record:

  • PENDING: Queued for sync
  • SYNCING: Currently in a batch being transmitted
  • SYNCED: Successfully pushed to server
  • FAILED: Encountered error, needs retry
  • QUARANTINED: Persistent failures, needs manual intervention

Create a sync manifest that tracks each record’s state, attempt count, and last error. When a batch fails with 504, mark only the records in that batch as FAILED, not the entire queue. This allows other records to proceed while problematic ones are isolated.

Practical Implementation: Modify your sync endpoint call to include a batch identifier and sequence number:

POST /crm/v2/mobile/sync/batch
Headers: {
  X-Sync-Batch-ID: "uuid-v4",
  X-Batch-Sequence: "1/5"
}

This allows you to track which specific batches succeeded or failed. On the server side (if you control the middleware), implement idempotency checks using the batch ID to prevent duplicate record creation when retrying.

Timeout Prevention: While you can’t change Zoho’s gateway timeout, you can work within it. Measure your average record processing time during successful syncs. If 30 records process in 35 seconds, that’s your safe threshold. Build in a 25% buffer for network variability, giving you a target of ~22-25 records per batch.

Monitoring and Alerting: Add telemetry to your mobile app to track:

  • Average sync duration per record
  • Batch size vs success rate correlation
  • Specific record types causing delays
  • Network conditions during failures

This data will help you continuously optimize batch sizes and identify problematic record patterns.

User Experience: Show sync progress at the record level, not batch level. Display: “Syncing 45 of 150 records” rather than generic “Syncing…” This transparency helps sales reps understand what’s happening and builds confidence that their data isn’t lost.

With these changes, your 504 errors should virtually disappear, and any that do occur will be gracefully handled without losing data or requiring user intervention.

Check your payload compression settings. We were hitting similar timeouts until we enabled gzip compression on the mobile client. A 2.3MB payload compressed down to about 400KB, which drastically reduced transmission time and eliminated most timeout issues. Also verify that your mobile app isn’t including unnecessary fields or attachments in the sync payload. Review the actual JSON being sent - often there’s bloat from base64-encoded images or redundant relationship data that can be stripped out.

The retry logic needs to be smarter than just exponential backoff on the same large batch. Implement a fallback strategy: first retry with the full batch, but if that fails, automatically split into smaller chunks (25-30 records each) and retry those individually. Track which specific records failed and isolate them for separate handling. We use a “sync queue manager” pattern where failed records get moved to a separate retry queue with their own processing logic. This prevents one problematic record from blocking the entire sync operation.