EDA Events

EDA Events: Standards and Guidelines

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:

alt text

[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:

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