Transactions
specdraftimplproposalAtomic and batch transactions over multiple feature collections.
Scope
Provides a single resource POST /transactions that accepts a transaction document describing one or more insert, replace, update or delete actions across one or more feature collections of the API. The canonical request encoding is application/ogc-tx+json; the response is application/json.
Two semantics are supported: atomic transactions execute all actions as a single database transaction (rollback on failure), batch transactions execute each action independently and report per-action results.
For interoperability with WFS 2.0 producers the building block can additionally accept wfs:Transaction XML payloads in atomic mode.
The Prefer request header is honoured per RFC 7240: return=representation (the default), return=minimal, or return=none controls how much of the transaction response is returned; handling=strict validates every insert and replace payload against the feature-type schema before any provider write (this only takes effect when the collection has schema validation configured \u2014 JSON Schema for GeoJSON payloads, XSD for GML payloads). respond-async is rejected with 501.
The Content-Crs request header declares the CRS of coordinates in the request body. When omitted, the API's default CRS (CRS84 unless overridden) is assumed; values that are syntactically invalid or name a CRS not in the API's supported list are rejected with a 4xx error.
Both successful and atomic-failed responses use the same Part 11 Transaction Response document shape (with summary, the per-action result arrays, and an exceptions[] array when applicable), so clients do not need to branch on the response status to parse the body.
Limitations
The following restrictions apply:
- Provider and request scope:
- Only feature types from an SQL feature provider that supports mutations
(datasetChanges.modeCRUD) are supported. - Asynchronous transactions are not supported.
- Responses are always JSON; the WFS
wfs:TransactionResponseXML response is not produced. wfs:TransactionXML payloads are accepted in atomic mode only.- Filters in
update,replace, anddeleteactions: - Filters are restricted to selecting features by id. JSON action bodies accept either a
CQL2IN(<id-property>, [...])or<id-property> = ...expression, where<id-property>is the schema name (or alias, if declared) of the feature type's
property with roleID; other CQL2 predicates (comparison, spatial, temporal, or
boolean operators on regular properties) are rejected with a 4xx error. wfs:TransactionXML accepts onlyfes:ResourceId/@rid; no otherfes:Filterelement
types are recognised.updatesemantics:- An
updateaction applies property-level partial updates to a single existing feature in
place: each touched property is translated into a native SQLUPDATE(for columns on the
feature's main table, including geometries) or aDELETE-then-INSERTagainst the
associated child table (forVALUE_ARRAYandOBJECT_ARRAYproperties). All statements
run on the same session connection as the rest of the transaction, so anupdatecan
target a feature that wasinserted,replaced,updated, or whose junction rows were
touched earlier in the same atomic request. - The set of properties that may be the target of a partial update is governed by
updatablePropertieson the collection's TRANSACTIONS configuration; a property whose
canonical path is not in that list is rejected with a 4xx error. The whitelist defaults
to an empty list, which disables partial updates for the collection. Entries are the
schema property identifiers, joined by.(e.g.lifetime.endfor a nested property,namefor a top-level scalar). - Property paths are resolved against the feature schema and the input format's
useAlias
setting. JSON-transactionnameanddeletepaths use the canonical dotted form (the.separator; XPath-style/is reserved forwfs:ValueReference). Awfs:Update'swfs:ValueReferencefollows the XPath form and must include the intermediate
object-type element (e.g.lifetime/Lifetime/end); XML namespace prefixes are stripped,
only local names and the path structure are significant. - When the filter selects more than one id (e.g.
IN(id, ['a','b'])or multiplefes:ResourceId/@rid), the same patch is applied to every selected feature. - An absent value (a
<wfs:Property>with no<wfs:Value>, or a JSON-txdeleteentry)
clears the property: SQLNULLfor a column on the main table, or an empty result for
aVALUE_ARRAY/OBJECT_ARRAY(all junction rows for that property are removed and
none are re-inserted). - Geometries: a
wfs:Updatemay set a geometry property by placing the corresponding GML
geometry element (e.g.<gml:Point>) inside<wfs:Value>. A JSON-transaction update
uses a GeoJSON geometry object as the property value. Both forms re-use the same
CRS-aware encoder asinsert/replace. The geometry property must live on the
feature's main table; geometry on a child table is not supported. - Value arrays (
VALUE_ARRAY): multiple sibling<wfs:Property>elements with the samewfs:ValueReferencecollapse into one array on the WFS side (each value contributes
one element). A JSON-transaction update uses a JSON array of scalars. The whole array
is replaced. - Object arrays (
OBJECT_ARRAY): awfs:Updatesets anOBJECT_ARRAYproperty by
placing one or more object-type wrapper elements inside<wfs:Value>(one per array
element); a JSON-transaction update uses a JSON array of objects. Object keys / child
element local names are matched against the array's schema in the same way as scalar
paths (id vs alias peruseAlias); unknown keys are silently ignored. The whole array
is replaced. Nested object children inside an array element, M:N junctions, andFEATURE_REFarrays are not yet supported.
Conformance Classes
The building block is based on the conformance classes "Transactions", "Atomic Semantics", "Batch Semantics", "JSON Encoding" and "Features" from the Draft OGC API - Features - Part 11: Atomic and Batch Transactions.
Configuration
Options
| Name | Default | Description | Type | Since |
|---|---|---|---|---|
buildingBlock | Always TRANSACTIONS. | string | v2.0 | |
enabled | false | Enable the building block? | boolean | v2.0 |
atomic | true | Advertises the conformance class for atomic transactions. When enabled, requests without a semantic parameter or with semantic=atomic are executed as a single database transaction; any failure rolls back the whole request. | boolean | v4.8 |
batch | true | Advertises the conformance class for batch transactions. When enabled, requests with semantic=batch execute each action independently and report per-action results, including exceptions for failures. | boolean | v4.8 |
wfsTransaction | false | Enables decoding of WFS 2.0 wfs:Transaction XML payloads at POST /transactions. Only valid when atomic is true and the GML building block is enabled. | boolean | v4.8 |
defaultSemantic | ATOMIC | Semantic applied to requests that do not specify one. The default matches the OGC API Features Part 11 specification default. | string | v4.8 |
maxActionsPerRequest | 0 | Optional upper bound on the number of actions per request. A value of zero or null disables the limit. | number | v4.8 |
collectErrors | false | Only relevant for atomic semantics. When enabled, a failing action does not stop the processing of the transaction: the remaining actions are still executed, every error is collected, and the response reports all of them, while all changes are still rolled back. This lets clients fix every error in a large transaction in one pass instead of one error per attempt. Later actions see the changes of earlier successful actions, but not those of failed actions \u2014 an action that depends on a failed action therefore typically reports a follow-on error. Each action adds a small database overhead (a savepoint), which can be noticeable in very large transactions. Requires a SQL feature provider; otherwise the option is ignored. When disabled, processing stops at the first error, the remaining actions are skipped, and only the first error is reported. | boolean | v4.8 |
updatableProperties | [] | Whitelist of feature properties that may be the target of a partial update (the wfs:Update action of a wfs:Transaction, or the JSON-transaction update action). Each entry is a property path written as the schema property identifiers joined by ., e.g. lifetime.end for a nested property or name for a top-level scalar. Path segments are always the canonical schema identifiers, independent of the input format's alias setting. A partial update whose property path is not in this list is rejected with a 4xx error. Entries set at the API level apply to every collection; entries set on a specific collection are merged with the API-level list (duplicates de-duplicated). When the effective list for a collection is empty, partial updates are disabled for that collection. | array | v4.8 |
transactionSetup | null | SQL statements executed on the database transaction right after it begins, before any action runs. Typical uses are transaction-scoped settings ( SET LOCAL \u2026) or calling a setup function. Each entry is a single statement run verbatim, in order, on the provider's transaction connection (PostgreSQL/PostGIS feature providers only). The always, strict and lenient lists select which statements run depending on the request's Prefer: handling preference. A statement that fails aborts the transaction. | object | v4.8 |
preCommit | null | SQL statements executed on the database transaction right before it is committed. Typical uses are calling functions that update derived data or verify consistency. Each entry is a single statement run verbatim, in order, on the provider's transaction connection (PostgreSQL/PostGIS feature providers only). The always, strict and lenient lists select which statements run depending on the request's Prefer: handling preference. A statement that raises an error aborts the transaction and rolls it back; a statement that only emits a warning (RAISE WARNING / RAISE NOTICE) lets the transaction commit and the warning is returned in the response. The error and warning text is relayed verbatim into the response (exceptions and warnings), and the statements run at the database level without access to the request actions, so write RAISE messages that identify the affected feature(s) \u2014 e.g. include the feature identifier \u2014 to make the response actionable. | object | v4.8 |
updatablePropertyPaths | array | v2.0 |
This building block does not require or support any additional configuration files.
Examples
- buildingBlock: TRANSACTIONS
enabled: true
atomic: true
batch: true
wfsTransaction: false
defaultSemantic: ATOMIC
collectErrors: true
Per-collection partial-update whitelist (allows wfs:Update / JSON-transaction update
actions to set the listed scalar/datetime/geometry/VALUE_ARRAY/OBJECT_ARRAY properties):
collections:
places:
api:
- buildingBlock: TRANSACTIONS
updatableProperties:
- location # geometry on the main table
buildings:
api:
- buildingBlock: TRANSACTIONS
updatableProperties:
- name # top-level scalar
- lifetime.end # nested property
- tags # VALUE_ARRAY
- addresses # OBJECT_ARRAY
Transaction-lifecycle hooks (PostgreSQL/PostGIS providers). Statements are selected by the
request's Prefer: handling preference; a pre-commit error rolls the transaction back, a
pre-commit warning lets it commit and is returned in the response:
- buildingBlock: TRANSACTIONS
transactionSetup:
always:
- SET LOCAL myapp.geometry_validation.enabled = true
strict:
- SET LOCAL myapp.geometry_validation.error_if_invalid = true
lenient:
- SET LOCAL myapp.geometry_validation.error_if_invalid = false
preCommit:
always:
- SELECT myapp.update_derived_data()
strict:
- SELECT myapp.assert_consistency()