Skip to content

Concurrency Control

Overview

Concurrency control prevents accidental overwrites when multiple users edit the same record.

If two users open the same record and both make changes:

  1. The first user to save succeeds.
  2. The second user's local copy becomes stale.
  3. If the second user tries to save, they are informed that the record was updated elsewhere.
  4. The second user is prompted to refresh the form.

Current Scope

Concurrency checks are currently enforced for Forms only.

Support for additional platform areas is planned for future releases.

Project Setting

Concurrency checking is controlled per project in:

Project Settings -> Enforce Concurrency Checks (True / False)

  • True: Concurrency validation is enabled.
  • False: Concurrency validation is disabled.

Cache Behavior

The Enforce Concurrency Checks setting is cached.

After changing the value, allow up to 5 minutes for the change to take effect.

Header Requirements

To ensure concurrency control functions correctly, the following headers must be allowed and forwarded through the stack (Portal Backend and APIM):

<allowed-headers>
        <header>Content-Type</header>
        <header>Authorization</header>
        <header>x-functions-key</header>
        <!-- Legacy headers (deprecated — will be removed in a future release) -->
        <header>x-concurrency-token</header>
        <header>x-concurrency-token-source</header>
        <header>x-auth-failure-reason</header>
        <header>x-master-correlation-id</header>
        <header>x-pf-system-properties</header>
        <header>x-dem-requested-auth-scope</header>
        <header>Demtoken</header>
        <header>package_version</header>
        <!-- New standardized headers -->
        <header>Pf-Concurrency-Token</header>
        <header>Pf-Concurrency-Token-Source</header>
        <header>Pf-Auth-Failure-Reason</header>
        <header>Pf-Master-Correlation-Id</header>
        <header>Pf-System-Properties</header>
        <header>Pf-Requested-Auth-Scope</header>
        <header>Pf-Dem-Token</header>
        <header>Pf-Package-Version</header>
</allowed-headers>

Migration Note: During the transition period, both legacy (x-*, Demtoken) and new (Pf-*) headers must be allowed. The legacy headers are deprecated and will be removed in a future release.

Portal Backend support for these headers is available from 2026_MAR_03 onward.

APIM may still require manual updates depending on your environment.

Target APIM APIs:

  • apolloapi
  • apollodemapi
  • testharnessapi

customerconfig.json Guidance

Update your own customerconfig.json APIM CORS allowedHeaders lists to include both the legacy and new header values:

  • x-concurrency-token (legacy)
  • x-concurrency-token-source (legacy)
  • x-auth-failure-reason (legacy)
  • x-master-correlation-id (legacy)
  • x-pf-system-properties (legacy)
  • x-dem-requested-auth-scope (legacy)
  • Demtoken (legacy)
  • Pf-Concurrency-Token
  • Pf-Concurrency-Token-Source
  • Pf-Auth-Failure-Reason
  • Pf-Master-Correlation-Id
  • Pf-System-Properties
  • Pf-Requested-Auth-Scope
  • Pf-Dem-Token
  • Pf-Package-Version

Use the following sanitized example as a template and replace placeholders with your own environment values:

{
    "apim": [
        {
            "adminEmail": "<your-admin-email>",
            "identifier": "<your-apim-identifier>",
            "name": "<your-apim-resource-name>",
            "organizationName": "<your-organization-name>",
            "apis": [
                {
                    "identifier": "apollodemapi",
                    "cors": {
                        "allowedHeaders": [
                            "Content-Type",
                            "Authorization",
                            "x-functions-key",
                            "x-concurrency-token",
                            "x-concurrency-token-source",
                            "x-auth-failure-reason",
                            "x-master-correlation-id",
                            "x-pf-system-properties",
                            "x-dem-requested-auth-scope",
                            "Demtoken",
                            "package_version",
                            "Pf-Concurrency-Token",
                            "Pf-Concurrency-Token-Source",
                            "Pf-Auth-Failure-Reason",
                            "Pf-Master-Correlation-Id",
                            "Pf-System-Properties",
                            "Pf-Requested-Auth-Scope",
                            "Pf-Dem-Token",
                            "Pf-Package-Version"
                        ]
                    }
                },
                {
                    "identifier": "testharnessapi",
                    "cors": {
                        "allowedHeaders": [
                            "Content-Type",
                            "Authorization",
                            "x-functions-key",
                            "x-concurrency-token",
                            "x-concurrency-token-source",
                            "x-auth-failure-reason",
                            "x-master-correlation-id",
                            "x-pf-system-properties",
                            "x-dem-requested-auth-scope",
                            "Demtoken",
                            "package_version",
                            "Pf-Concurrency-Token",
                            "Pf-Concurrency-Token-Source",
                            "Pf-Auth-Failure-Reason",
                            "Pf-Master-Correlation-Id",
                            "Pf-System-Properties",
                            "Pf-Requested-Auth-Scope",
                            "Pf-Dem-Token",
                            "Pf-Package-Version"
                        ]
                    }
                },
                {
                    "identifier": "apolloapi",
                    "cors": {
                        "allowedHeaders": [
                            "Content-Type",
                            "Authorization",
                            "x-functions-key",
                            "x-concurrency-token",
                            "x-concurrency-token-source",
                            "x-auth-failure-reason",
                            "x-master-correlation-id",
                            "x-pf-system-properties",
                            "x-dem-requested-auth-scope",
                            "Demtoken",
                            "package_version",
                            "Pf-Concurrency-Token",
                            "Pf-Concurrency-Token-Source",
                            "Pf-Auth-Failure-Reason",
                            "Pf-Master-Correlation-Id",
                            "Pf-System-Properties",
                            "Pf-Requested-Auth-Scope",
                            "Pf-Dem-Token",
                            "Pf-Package-Version"
                        ]
                    }
                }
            ]
        }
    ]
}

Header Migration

The platform is standardizing custom HTTP headers under the Pf- prefix, following IETF BCP 178 (RFC 6648) which deprecates the X- prefix for new parameters.

Old vs New Header Mapping

Old Header (Legacy) New Header Direction
x-concurrency-token Pf-Concurrency-Token Request + Response
x-concurrency-token-source Pf-Concurrency-Token-Source Response
x-auth-failure-reason Pf-Auth-Failure-Reason Response
x-master-correlation-id Pf-Master-Correlation-Id Request + Response
x-pf-system-properties Pf-System-Properties Response
x-dem-requested-auth-scope Pf-Requested-Auth-Scope Request
Demtoken / demToken Pf-Dem-Token Request
package_version Pf-Package-Version Response

Migration Timeline

  1. Phase 1 — Dual support (current): Both old and new headers are accepted. The API emits both on responses. APIM and Portal Backend must allow both sets through.
  2. Phase 2 — Frontend migration: Frontend code sends both old and new headers. No breakage during this phase.
  3. Phase 3 — Legacy removal (future): Old x-* headers and Demtoken will be removed in a future release. All consumers must have migrated to Pf-* headers by then.

APIM Changes Required

All three target APIs (apolloapi, apollodemapi, testharnessapi) need both legacy and new headers in their allowedHeaders CORS lists as shown in the example above. Note that apolloapi does not currently need x-dem-requested-auth-scope / Pf-Requested-Auth-Scope or package_version / Pf-Package-Version (those are DEM-specific), but adding them does no harm.

No existing headers should be removed until Phase 3.