EDA Events
EDA Events: Standards and Guidelines
- EDA Events: Standards and Guidelines
- Purpose and intended audience
- Messages and Event Types
- Event standards and conventions
Purpose and intended audience
Purpose of this document is to provide wholistic, concise rules, standards and guidelines that cover all aspects of Event Driven Architecture (EDA) implementation across the banking domains landscape. This includes:
- Messages and Event types, differences, usage
- Standards for Events design, for each type
- Standards and guidelines for the topic design
Intended audience are all interested parties and stakeholders for the API management, including, but not limited to: Software Architects, API owners, Developers, Executives, Product Managers.
Messages and Event Types
Here is division of Message types in our EDA :
Events
- Records (AKA Event Carried State Transfer (ECST)) - Events that carry the complete current state of a business entity, enabling consumers to maintain local copies without additional queries.
- Domain (Delta) Events - Events that carry only the changes (deltas) that occurred to a business entity, requiring consumers to apply changes to existing state.
Messages in general sense.
- Commands - Messages that request a specific action to be performed by a target system or service.
- Queries - Messages that request information retrieval without causing state changes.
- Replies - Messages sent in response to commands or queries, containing results, acknowledgments, or error information.
- Notification - Messages that inform about something that happened, without expecting any specific action or response. Usually used towards end user interface (mobile app, SMS, email, etc).
Record (ECST, Snapshot)
Also known as Event Carry State Transfer (ECST) events are records of an aggregate after a change. Intended for the Event consumers that need latest state. Those events are CUD type (create, update, delete). Also those type of events are most common in integration standardized APIs. They simply communicate latest available state of the aggregate, without details WHY that change occurred. Their aim is to provide a way for consumers in another domains to catch up with the latest state of aggregate ASAP.
Domain Events (Delta)
Domain (AKA Delta) events are milestone events in lifecycle of an aggregate. Those are produced for event consumers that care about what happened. It requires from the consumer to know about some business logic of the domain which emits delta events.
Those events can be public or internal for the domain. Internal domain events are usually much more numerous compared to ECST or delta events, and are meant for the intra domain usage, within bounded context.
Command
🚧 Work in progress
Query
🚧 Work in progress
Reply
🚧 Work in progress
Notification
🚧 Work in progress
Events vs Messages Comparison Table
Aspect | ECST Events | Delta Events | Commands | Queries | Replies | Notifications |
---|---|---|---|---|---|---|
Purpose | State synchronization | Change tracking | Action request | Information request | Response delivery | Information broadcast |
Content | Full entity state | Only changes | Action parameters | Query parameters | Results/status | Event summary |
Consumers | Build read models | Apply incremental changes | Specific service | Specific service | Original requester | Any interested party |
Response | None expected | None expected | Reply expected | Reply expected | None (is the response) | None expected |
Correlation | Not applicable | Not applicable | Uses correlation ID | Uses correlation ID | Contains correlation ID | Not applicable |
Retention | Can be compacted | Must retain all | Can be deleted after reply | Can be deleted after reply | Can be deleted after delivery | Can be deleted after broadcast |
Ordering | Per entity | Per entity | Per recipient | Not critical | Must match request order | Not critical |
Event standards and conventions
Events format
We use Cloud Events standard for all event structure https://cloudevents.io/, with more specific cloud events standards for our usage defined in our common event specification, which can be found here
In the next illustration we will dive deeper into actual structure of the ECST and Delta events:
[Image 2] Event structure for ECST and Delta events
Image 2 shows structure of Events that we adopted. Let us give more light for each section:
Header
Most of the fields in header comes directly from Cloud Events (CE) standard. Left hand fields specversion, id, type and source are mandatory. While, dataSchema, subject and time are context attributes in header. Fields traceParent and traceState are extension fields, not part of CE standard, meant to be used for tracing business transactions through events and for auditing purposes.
Header also contains broader Context for the event, that serves as the business related information around that event instance, which can help event consumer to understand under which conditions event was produced.
Data
Data part of event contains actual payload, specific for the event type.
Depending on event type, record or Domain Event we can have:
- State for the aggregate after the change, which contains entities and value objects that belong to that aggregate. For the 'deleted' events, state is null.
- Domain (delta) event is the representation of the business situation and change itself. For domain events it is needed that consumers have some sufficient understanding of business logic of the event producer.
Record (ECST) vs Domain (Delta) Events
Since we rely heavily on DDD for organizing our information and integration complexity in Banking, we need to delineate Events based also on internal or external for a particular domain:
Public vs Internal Events
Aspect | Public Events | Internal Events |
---|---|---|
Scope | Cross-domain integration | Within single domain |
Consumers | Multiple external domains | Domain-internal services |
Schema Stability | High - breaking changes impact multiple teams | Medium - controlled by single team |
Semantic Richness | Business-focused, minimal technical details | Can include domain-specific technical details |
Governance | Requires cross-team approval | Team-internal decisions |
Retention | Long-term for compliance | Can be shorter, business-driven |
Documentation | Extensive external documentation | Internal team documentation |
Record (ECST)
Record events are CUD events (create, update, delete) for a certain aggregate. They simply carry value for the latest state of the aggregate. It serves mostly for the downstream consumers to simply have local copy of the original For master data domains like Party, ECST events are mandatory, because most of
Public and internal Domain Events (Delta)
Delta events are useful for the domains where changes are more interesting than pure state. Example for this is account-data domain where delta of the latest change would be broadcasted to all interested consumers. Domain events can be public (part of standardized integration API) and internal (only used inside particular domain, such is lending or payments).
Topic Naming convention for events and records
General rules for topic names
- topic components are separated with
.
symbol - multiple word items are separated with
-
symbol
Naming format
[<tenant>.]<environment>.<access>.<domain>.<channel>[.<aggregate>]
- environment possible values: DEV, FAT, PERF, FRVT, PREVIEW, SRVT, HOTFIX, EDIT, DRVT, SIT, UAT, CRVT, STAGING, PROD, DR
- access possible values: public, internal
- Possible channel values:
records, events, commands, queries, replies
Examples:
nlb-me.dev.public.current-account.records.arrangement
prod.public.party.events.individual
nlb-rs.prod.internal.party.records.individual
uat.internal.party.events.individual
Events header fields conventions
Note: bolded field name means it is mandatory
Field name | Type | Description | Example values |
---|---|---|---|
id | string | Identifies the event. Producers MUST ensure that source + id is unique for each distinct event. If a duplicate event is re-sent (e.g. due to a network error) it MAY have the same id. Consumers MAY assume that Events with identical source and id are duplicates. |
b84bea58-92b1-4f8d-8238 |
source | URI Reference | Source represents domain and aggregate where event originates from. Format of source URI is like this: <core-code>/<domain-name>/<aggregate> |
pub/current-account/current-accounts bapo/party/individual |
type | string | Describes the type of event related to the originating occurrence. type field format general rules: - type value components are separated with . symbol - multiple word items are separated with - symbol - for domain events last part of the name prior to the version must be either a verb type field format differs for the each major event class: Record event: - <namespace>.<domain>.<aggregate>.v<major> - <namespace>.<domain>.<aggregate>.<entity>.v<major> Domain event: - <namespace>.<domain>.<aggregate>.<action-name>.v<major> |
Record events examples - "asee.device.payment-card.v1" - "asee.party.individual.v1" - "asee.party.individual.contact-points.v1" Domain events examples: - "asee.device.payment-card.replaced.v1" - "asee.party.individual.death-reported.v1" - "asee.party.organization.contact-point-added.v1" |
specversion | string | The version of the CloudEvents specification which the event uses. This enables the interpretation of the context. Compliant event producers MUST use a value of 1.0 when referring to this version of the specification. | 1.0 |
time | string | Timestamp of when the occurrence happened. If the time of the occurrence cannot be determined then this attribute MAY be set to some other time (such as the current time) by the CloudEvents producer, however all producers for the same source MUST be consistent in this respect. In other words, either they all use the actual time of the occurrence or they all use the same algorithm to determine the value used. | 2025-09-07T11:22:33.123+02:00 |
recordedTime | string | Time when the event was recorded, usually it is the time the event was produced and delivered to message broker. | 2025-09-08T15:30:00.123+02:00 |
datacontenttype | string | Content type of data value. This attribute enables data to carry any type of content | application/json avro/binary application/xml |
dataschema | string | Content type of data value. This attribute enables data to carry any type of content | (https://schemas.asee.io/lending/loan/fee-accrued.v1.json) |
subject | string | This describes the subject of the event in the context of the event producer (identified by source). Identifying the subject of the event in context metadata (opposed to only in the data payload) is particularly helpful in generic subscription filtering scenarios where middleware is unable to interpret the data content. | payment number, example 732987932793299328 partyID, example 123456213231 |
authtype | string | An enum representing the type of principal that triggered the occurrence. Valid values are: - app_user : An end user of an application. Examples include an AWS cognito, Google Cloud Identity Platform, or Azure Active Directory user. - user : A user account registered in the infrastructure. Examples include developer accounts secured by IAM in AWS, Google Cloud Platform, or Azure. - service_account : A non-user principal used to identify a service. - api_key : A non-user API key - system : An obscured identity used when a cloud platform or other system service triggers an event. Examples include a database record which was deleted based on a TTL. - unauthenticated : No credentials were used to authenticate the change that triggered the occurrence. - unknown : The type of principal cannot be determined and is unknown. |
api_key user |
authid | string | A unique identifier of the principal that triggered the occurrence. This specification makes no statement as to what this value ought to be, however including personally identifiable information (PII) in a CloudEvent is often considered inappropriate, so some indirect reference (e.g. a hash or label of an API key) might be considered. | b84bea23-92b1-4f8d-8238-19219dd1a445 |
traceparent | string | Identifies the incoming request in a distributed tracing system. Contains a version, trace ID, span ID, and trace options. | 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01 |
tracestate | string | A comma-delimited list of key-value pairs that contains additional vendor-specific trace identification information across different distributed tracing systems and is a companion attribute for the traceparent field. It also conveys information about the request’s position in multiple distributed tracing graphs.. | rojo=00f067aa0ba902b7,congo=t61rcWkgMzE |
sequence | string | Value expressing the relative order of the event. This enables interpretation of data supercedence.The sequence MUST start with a value of 1 and increase by 1 for each subsequent value (i.e. be contiguous and monotonically increasing).. | 123456 |
sequencetype | string | Specifies the semantics of the sequence attribute. Default value for this is Integer . Here are some rules for this value: -The values of sequence are string-encoded signed 32-bit Integers. -The sequence MUST start with a value of 1 and increase by 1 for each subsequent value (i.e. be contiguous and monotonically increasing). -The sequence wraps around from 2,147,483,647 (231 -1) to -2,147,483,648 (-231). |
Integer |
partitionkey | string | Defines an attribute for use by message brokers and their clients that support partitioning of events, typically for the purpose of scaling. A partition key for the event, typically for the purposes of defining a causal relationship/grouping between multiple events. In cases where the CloudEvent is delivered to an event consumer via multiple hops, it is possible that the value of this attribute might change, or even be removed, due to protocol semantics or business processing logic within each hop. |
The ID of the entity that the event is associated with c64bea56-92b1-4f8d-8238-19219dd1a982 |
productCode | string | Represents product identification, where product is particular system which serves some well defined and bounded functionality. | 54890909827FN |
arrangementNumber | string | Identifier of the product / service agreement this fee pertains to. This is the identifier that customer uses to refer to a loan, deposit, current account etc. 12321345288718171 |
|
accountNumber | string | Identifier of the account. One account can be associated with multiple products and arrangements. | 9876543 |
customerNumber | string | Identifier of the customer associated with the agreement | 008718171 |
initiatorNumber | string | Sometimes account number of the actual initiator of the action does not equals to the account number which is affected. Here we have separate field which contains account number of the person which initiated event. | 4567890 |
commandCode | string | Human readable string representing command | c-123abc |
commandId | string | Identifier of the command associated with the event | rrq0oaouroauo08808ra07a08 |
agentId | string | Identifier of the agent (bank employee usually) | 0012389809 |
transactoinId | string | Unique ID of transaction which triggered creation of that event. | 12321345288718171 |
transactoinCode | string | Transaction code, human readable | abc1234 |
OUCode | string | Organization Unit code, human readable | BankAbc-Unit123 |
Branch | string | Organization branch code, human readable | BankAbc-Location123 |
reason | string | reason why event occured | conditions a b c were met |
ATMCode | string | ATM device unique identifier | atm-abc998 |