TutorialMarch 2025 · 8 min read

Akeneo Incremental Sync: Export Only Changed Products (Not Everything)

A full export of 100,000 products every hour is wasteful — most of those products haven't changed. Akeneo's incremental sync mechanism lets you fetch only the products modified since your last run. Here's how it works and how to implement it.

What incremental sync means in the Akeneo context

"Incremental sync" (also called delta export or differential sync) means: on each run, fetch only the data that changed since the previous run.

Full export

  • • Fetches all 100,000 products
  • • 20–30 minutes for large catalogs
  • • Heavy on Akeneo API rate limits
  • • Use for: initial load, weekly refresh

Incremental export ✓

  • • Fetches only 50–500 changed products
  • • Typically completes in seconds
  • • Minimal API usage
  • • Use for: hourly/daily ongoing sync

How Akeneo's updated_after filter enables delta exports

The Akeneo REST API's /products endpoint supports a search parameter that can filter by update timestamp:

# Fetch products updated after 2025-03-01T00:00:00Z
GET /api/rest/v1/products
  ?search={"updated":[{"operator":">","value":"2025-03-01T00:00:00Z"}]}
  &with_attribute_options=true
  &limit=100

# The response includes only products where:
#   product.updated > "2025-03-01T00:00:00Z"
# Newly created products are also included (created > timestamp)

The same filter works on the /product-models endpoint for fetching changed product model hierarchies.

Important timestamp format: Akeneo requires ISO 8601 format with time component. "2025-03-01" will not work — use "2025-03-01T00:00:00Z".

State tracking: how SyncPIM remembers what changed

For incremental sync to work, you need to persist the timestamp of your last successful export between runs. Manual implementation:

# Python example: state tracking with a JSON file
import json
from datetime import datetime, timezone
from pathlib import Path

STATE_FILE = "sync_state.json"

def get_last_export_time():
    if Path(STATE_FILE).exists():
        state = json.loads(Path(STATE_FILE).read_text())
        return state.get("last_export")
    return None  # None = full export needed

def save_export_time(timestamp: str):
    Path(STATE_FILE).write_text(json.dumps({
        "last_export": timestamp
    }))

# Usage:
last_export = get_last_export_time()
run_start = datetime.now(timezone.utc).isoformat()

if last_export:
    products = fetch_products_updated_after(last_export)
    print(f"Incremental: fetched {len(products)} changed products")
else:
    products = fetch_all_products()
    print(f"Full export: fetched {len(products)} products")

upsert_products(products)
save_export_time(run_start)  # Save AFTER successful upsert

SyncPIM handles this automatically — no state file, no database table needed. Each configuration tracks its last successful run timestamp internally and uses it on the next scheduled or manual run.

Setting up scheduled incremental exports

The recommended production setup:

  • Daily incremental exports (Essential plan): sufficient for most B2B catalogs where products don't change minute-by-minute.
  • Hourly incremental exports (Professional plan): ideal for active e-commerce catalogs where pricing or stock changes frequently.
  • Weekly full export (any plan): run automatically once a week to catch any edge cases (deletions, orphaned records) that incremental sync might miss.

In SyncPIM, set the schedule in the configuration's "Job Mode" settings. See the job mode setup guide for the step-by-step UI walkthrough.

Troubleshooting: what if a product update is missed?

Product updated in Akeneo but not in database

Cause: Export ran before the product was saved, or state tracking timestamp was corrupted

Fix: Run a manual full export to reconcile. Check the SyncPIM dashboard for any failed runs around the time of the missed update.

Deleted products remain in database

Cause: Akeneo's updated_after filter doesn't return deleted products — they simply disappear

Fix: Use SyncPIM's soft-delete mode (marks records as deleted instead of removing them) or run a weekly full export that reconciles deletions.

Incremental export returns 0 products but changes exist in Akeneo

Cause: Timestamp timezone mismatch or Akeneo's updated field not reflecting the change

Fix: Ensure timestamps are in UTC. Some Akeneo import tools don't update the product's updated_at field — check if your Akeneo instance updates timestamps on import.

State file / timestamp corrupted after a crash

Cause: Process killed mid-export before state was saved

Fix: The safest recovery is to re-run a full export. SyncPIM handles this automatically by detecting incomplete runs.

Set up your first incremental sync

SyncPIM handles state tracking, scheduling, retries, and error alerts automatically. Start with 10 free exports.

Related