Skip to content

First Replication

This walkthrough copies remote data into your local database on a schedule. Afterwards, queries run fully locally — joinable, aggregatable, offline-capable.

When to replicate instead of delegate

You wantPick
Up-to-the-second dataDelegate
Joins across remote data and local data in SQLReplicate
Aggregations / analytics on remote dataReplicate
Resilience against remote outagesReplicate
Writes that must land in the system of recordDelegate (writable)

1. Declare a replicate consumption view

cds
using { API_BUSINESS_PARTNER as remote } from './external/API_BUSINESS_PARTNER';

service ExternalService {

    @federation.replicate: { schedule: 600000, preload: true, delta: { field: 'LastChangeDateTime' } }
    entity ReplicatedPartners as projection on remote.A_BusinessPartner {
        BusinessPartner         as ID,
        BusinessPartnerFullName as name,
        BusinessPartnerCategory as category,
        LastChangeDateTime
    };

}
  • schedule: 600000 — re-sync every 10 minutes via cds.spawn. Omit for manual-only mode.
  • preload: true — run one initial sync at server startup so the local table has data immediately, instead of staying empty until the first schedule tick. Use preload: { wait: true } to block boot until that first load finishes. See Initial load on startup.
  • delta: { field: 'LastChangeDateTime' } — only fetch records modified since the last successful run.
  • The plugin turns this projection into a local table (@cds.persistence.skip: false, @cds.persistence.table).

2. Activate the tracker tables

@federation.replicate is backed by the cds-data-pipeline engine, which persists its run state in two tracking tables (plugin.data_pipeline.Pipelines, plugin.data_pipeline.PipelineRuns). Adding cds-data-pipeline to your dependencies loads the engine, but the tracker schema is opt-in. Without it, boot fails on the first pipeline run with:

Error: no such table: plugin_data_pipeline_Pipelines

Pick one of these to bring the schema into your model:

  • Tracker tables only — add to any .cds file in your model (e.g. db/schema.cds):
cds
using from 'cds-data-pipeline/db';
  • Tracker tables + /pipeline management API — set management.reuse.api on the engine's cds.requires entry:
json
{
  "cds": {
    "requires": {
      "data-pipeline": {
        "impl": "cds-data-pipeline",
        "management": { "reuse": { "api": true } }
      }
    }
  }
}

Then deploy the schema via cds deploy (local / SQLite) or your HDI container (HANA). The plugin does no runtime DDL. See Feature activation for the full matrix and the "do not combine" rules.

3. Boot the app

bash
cds watch

On startup you'll see something like:

[cds-data-federation] scheduled replication ReplicatedPartners (every 600000ms)
[cds-data-federation] PIPELINE.READ ReplicatedPartners — initial full sync
[cds-data-federation] PIPELINE.WRITE ReplicatedPartners — 1234 records upserted

4. Query the local table

After the first sync:

http
GET /external/ReplicatedPartners?$filter=category eq 'Z001'&$orderby=name

This is a plain local SQL query. Join with other local tables, aggregate, filter — everything SQL supports.

Manual triggers and management

@federation.replicate entities are backed by the pipeline engine, which exposes an OData management service at /pipeline (enable it with management.reuse.api):

http
POST /pipeline/execute
Content-Type: application/json

{ "name": "ReplicatedPartners", "mode": "full" }

See the cds-data-pipeline Management Service for all management endpoints.

Pipeline Console

For a visual monitor, enable the pre-built UI with management.reuse.console: true on the data-pipeline requires entry (see Feature activation). Replicate entities registered by federation appear automatically in the console.

Pipeline landscape — federation replicate pipelines grouped by service

Pipeline detail — replicate run history and schedule controls

What you get for free

  • Idempotent UPSERT writes — re-runs produce no duplicates.
  • Concurrency guard — overlapping runs are detected via an optimistic UPDATE on the tracker table and return early.
  • Retry with exponential backoff + jitter (skips 4xx by default).
  • Async generator streaming — large datasets are never loaded fully into memory.
  • Three delta modes (timestamp, key, datetime-fields).
  • REST adapter with offset / cursor / page pagination — see the cds-data-pipeline REST adapter.

Extending the pipeline

Hook into the PIPELINE.READ / PIPELINE.MAP / PIPELINE.WRITE phases via the standard CAP service API:

javascript
const federation = await cds.connect.to('data-pipeline');

federation.before('PIPELINE.MAP', 'ReplicatedPartners', async (req) => {
    req.data.sourceRecords = req.data.sourceRecords.filter(r => !r.blocked);
});

See the programmatic API reference for the full hook signature.

Next steps

Released under the MIT License.