Slide 1

Slide 1 text

DEALING WITH CHANGE 
 IN EVENT SOURCED APPLICATIONS Michiel Rook 
 @michieltcs

Slide 2

Slide 2 text

@michieltcs #StandWithUkraine YOU?

Slide 3

Slide 3 text

@michieltcs #StandWithUkraine FAMILIAR WITH CQRS/ES THEORY?

Slide 4

Slide 4 text

@michieltcs #StandWithUkraine HOBBY PROJECT?

Slide 5

Slide 5 text

@michieltcs #StandWithUkraine APP IN PRODUCTION?

Slide 6

Slide 6 text

@michieltcs #StandWithUkraine QUICK RECAP

Slide 7

Slide 7 text

@michieltcs #StandWithUkraine - M A RT I N FOW L E R "Event Sourcing ensures that all changes to application state are stored as a sequence of events."

Slide 8

Slide 8 text

@michieltcs #StandWithUkraine ACTIVE RECORD VS. EVENT SOURCING Account Id Account number Balance 1234 12345678 € 50,00 ... ... ... Money Withdrawn Account Id 1234 Amount € 50,00 Money Deposited Account Id 1234 Amount € 100,00 Account Opened Account Id 1234 Account number 12345678

Slide 9

Slide 9 text

@michieltcs #StandWithUkraine COMMANDS TO EVENTS Deposit Money Account Id 1234 Amount € 100,00 data class DepositMoney( @TargetAggregateIdentifier val accountId: String, val amount: BigDecimal )

Slide 10

Slide 10 text

@michieltcs #StandWithUkraine COMMANDS TO EVENTS Deposit Money Account Id 1234 Amount € 100,00 command 
 handler @CommandHandler fun depositMoney(command: DepositMoney) { apply(MoneyDeposited( command.accountId, command.amount, GenericEventMessage.clock.instant())) }

Slide 11

Slide 11 text

@michieltcs #StandWithUkraine COMMANDS TO EVENTS Deposit Money Account Id 1234 Amount € 100,00 Money Deposited Account Id 1234 Amount € 100,00 command 
 handler data class MoneyDeposited( val accountId: String, val amount: BigDecimal, val instant: Instant )

Slide 12

Slide 12 text

@michieltcs #StandWithUkraine AGGREGATES An Aggregate handles Commands and generates Events based on the current state

Slide 13

Slide 13 text

@michieltcs #StandWithUkraine AGGREGATES @Aggregate class BankAccount { @AggregateIdentifier private lateinit var accountId: String private lateinit var accountNumber: String private lateinit var balance: BigDecimal @CommandHandler fun depositMoney(command: DepositMoney) { apply(MoneyDeposited( command.accountId, command.amount, GenericEventMessage.clock.instant())) } @EventHandler fun moneyDeposited(event: MoneyDeposited) { balance = balance.add(event.amount) } }

Slide 14

Slide 14 text

@michieltcs #StandWithUkraine AGGREGATE STATE Account number Balance 12345678 € 0,00 Account number Balance 12345678 € 100,00 Account number Balance 12345678 € 50,00 event 
 handler event 
 handler event 
 handler Money Withdrawn Account Id 1234 Amount € 50,00 Money Deposited Account Id 1234 Amount € 100,00 Account Opened Account Id 1234 Account number 12345678

Slide 15

Slide 15 text

@michieltcs #StandWithUkraine VALIDATING COMMANDS @CommandHandler @Throws(OverdraftDetectedException::class) fun withdrawMoney(command: WithdrawMoney) { if (balance.compareTo(command.amount) >= 0) { apply(MoneyWithdrawn( command.accountId, command.amount, GenericEventMessage.clock.instant())) } else { throw OverdraftDetectedException(accountNumber, balance, command.amount) } }

Slide 16

Slide 16 text

@michieltcs #StandWithUkraine TESTING AGGREGATES @TestInstance(TestInstance.Lifecycle.PER_CLASS) class BankAccountTest { private lateinit var fixture: AggregateTestFixture @BeforeEach fun createFixture() { fixture = AggregateTestFixture(BankAccount::class.java) } @Test fun noOverdraftsOnEmptyAccount() { fixture.given(accountOpened()) .`when`(WithdrawMoney(ACCOUNT_ID, WITHDRAW_AMOUNT)) .expectException(OverdraftDetectedException::class.java) } const val ACCOUNT_ID = "accountId" const val ACCOUNT_NUMBER = "3856625" }

Slide 17

Slide 17 text

@michieltcs #StandWithUkraine THIS IS ABOUT CHANGE

Slide 18

Slide 18 text

@michieltcs #StandWithUkraine -AG I L E M A N I F ES TO "Welcome changing requirements, even late in development."

Slide 19

Slide 19 text

@michieltcs #StandWithUkraine MODIFICATIONS

Slide 20

Slide 20 text

@michieltcs #StandWithUkraine EVENT SOURCING

Slide 21

Slide 21 text

@michieltcs #StandWithUkraine CHALLENGE!

Slide 22

Slide 22 text

@michieltcs #StandWithUkraine REPLAYS AND REBUILDS

Slide 23

Slide 23 text

@michieltcs #StandWithUkraine ANSWERING QUERIES

Slide 24

Slide 24 text

@michieltcs #StandWithUkraine BASED ON EVENTS

Slide 25

Slide 25 text

@michieltcs #StandWithUkraine QUERIES ACCOUNT OPENED ACCOUNT OPENED ACCOUNT CLOSED Number of active accounts?

Slide 26

Slide 26 text

@michieltcs #StandWithUkraine QUERIES MONEY DEPOSITED MONEY WITHDRAWN INTEREST RECEIVED Accounts with balance > €100? MONEY DEPOSITED MONEY WITHDRAWN

Slide 27

Slide 27 text

@michieltcs #StandWithUkraine PROJECTION ACCOUNT OPENED EVENT HANDLER # OF ACTIVE ACCOUNTS +1 ACCOUNT CLOSED EVENT HANDLER # OF ACTIVE ACCOUNTS -1

Slide 28

Slide 28 text

@michieltcs #StandWithUkraine PROJECTION EVENTS EVENT HANDLER(S) STORAGE

Slide 29

Slide 29 text

@michieltcs #StandWithUkraine CQRS

Slide 30

Slide 30 text

@michieltcs #StandWithUkraine UI

Slide 31

Slide 31 text

@michieltcs #StandWithUkraine DOMAIN UI COMMAND HANDLERS commands AGGREGATES

Slide 32

Slide 32 text

@michieltcs #StandWithUkraine DOMAIN UI COMMAND HANDLERS REPOSITORY EVENT STORE commands events AGGREGATES

Slide 33

Slide 33 text

@michieltcs #StandWithUkraine DOMAIN UI EVENT BUS EVENT HANDLERS COMMAND HANDLERS REPOSITORY DATABASE DATABASE EVENT STORE AGGREGATES commands events events

Slide 34

Slide 34 text

@michieltcs #StandWithUkraine DOMAIN UI EVENT BUS EVENT HANDLERS COMMAND HANDLERS REPOSITORY DATA LAYER DATABASE DATABASE EVENT STORE commands events events queries DTOs AGGREGATES

Slide 35

Slide 35 text

@michieltcs #StandWithUkraine PROJECTION class BankAccountProjections { private val activeAccounts: MutableMap = HashMap() @EventHandler fun onAccountOpened(accountOpened: AccountOpened) { val bankAccount = BankAccount( accountOpened.accountId, accountOpened.accountNumber, BigDecimal.ZERO) activeAccounts[accountOpened.accountId] = bankAccount } @EventHandler fun onAccountClosed(accountClosed: AccountClosed) { activeAccounts.remove(accountClosed.accountId) }

Slide 36

Slide 36 text

@michieltcs #StandWithUkraine PROJECTION fun findAccountById(accountId: String): Optional { return Optional.ofNullable(activeAccounts[accountId]) } fun getNumberOfAccounts(): Int { return activeAccounts.size } }

Slide 37

Slide 37 text

@michieltcs #StandWithUkraine PROJECTION @GetMapping("accounts/{accountId}") fun getAccountNumber(@PathVariable("accountId") accountId: String?): Optional { return bankAccountProjections.findAccountById(accountId!!) .map { obj: BankAccount -> obj.accountNumber } }

Slide 38

Slide 38 text

@michieltcs #StandWithUkraine PROJECTION @GetMapping("accounts/active") fun getNumberOfAccounts(): Int { return bankAccountProjections.getNumberOfAccounts() }

Slide 39

Slide 39 text

@michieltcs #StandWithUkraine NEW PROJECTION

Slide 40

Slide 40 text

@michieltcs #StandWithUkraine NEW STRUCTURE

Slide 41

Slide 41 text

@michieltcs #StandWithUkraine BASED ON EXISTING EVENTS

Slide 42

Slide 42 text

@michieltcs #StandWithUkraine REBUILDING STOP APP CLEANUP LOOP OVER EVENTS APPLY TO PROJECTION START APP

Slide 43

Slide 43 text

@michieltcs #StandWithUkraine ZERO DOWNTIME LOOP OVER EXISTING EVENTS APPLY TO NEW PROJECTION USE PROJECTION

Slide 44

Slide 44 text

@michieltcs #StandWithUkraine ZERO DOWNTIME NEW EVENTS QUEUE LOOP OVER EXISTING EVENTS APPLY TO NEW PROJECTION APPLY QUEUED EVENTS USE PROJECTION

Slide 45

Slide 45 text

@michieltcs #StandWithUkraine LONG RUNNING REBUILDS

Slide 46

Slide 46 text

@michieltcs #StandWithUkraine DISTRIBUTED

Slide 47

Slide 47 text

@michieltcs #StandWithUkraine DIVIDING THE WORK EVENT EVENT EVENT EVENT EVENT AGGREGATE EVENT

Slide 48

Slide 48 text

@michieltcs #StandWithUkraine DIVIDING THE WORK EVENT EVENT EVENT EVENT EVENT AGGREGATE INSTANCE EVENT INSTANCE

Slide 49

Slide 49 text

@michieltcs #StandWithUkraine DIVIDING THE WORK EVENT EVENT EVENT EVENT EVENT AGGREGATE INSTANCE EVENT INSTANCE

Slide 50

Slide 50 text

@michieltcs #StandWithUkraine DIVIDING THE WORK EVENT EVENT EVENT EVENT EVENT AGGREGATE INSTANCE EVENT EVENT EVENT EVENT INSTANCE

Slide 51

Slide 51 text

@michieltcs #StandWithUkraine DIVIDING THE WORK EVENT EVENT EVENT EVENT EVENT AGGREGATE INSTANCE EVENT EVENT EVENT INSTANCE EVENT EVENT EVENT EVENT

Slide 52

Slide 52 text

@michieltcs #StandWithUkraine DIVIDING THE WORK SELLER EVENT SELLER EVENT SELLER EVENT SELLER EVENT SELLER EVENT LISTING EVENT LISTING EVENT LISTING EVENT LISTING EVENT LISTING EVENT SELLER LISTING Seller Name Listing Date Listing Description ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

Slide 53

Slide 53 text

@michieltcs #StandWithUkraine DIVIDING THE WORK SELLER EVENT SELLER EVENT SELLER EVENT SELLER EVENT SELLER EVENT LISTING EVENT LISTING EVENT LISTING EVENT LISTING EVENT LISTING EVENT SELLER LISTING INSTANCE INSTANCE

Slide 54

Slide 54 text

@michieltcs #StandWithUkraine DIVIDING THE WORK SELLER EVENT SELLER EVENT SELLER EVENT SELLER EVENT SELLER EVENT LISTING EVENT LISTING EVENT LISTING EVENT LISTING EVENT LISTING EVENT SELLER LISTING INSTANCE INSTANCE ?

Slide 55

Slide 55 text

@michieltcs #StandWithUkraine BACKGROUND TASKS

Slide 56

Slide 56 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 57

Slide 57 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 58

Slide 58 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 59

Slide 59 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 60

Slide 60 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 61

Slide 61 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT TOKEN STORE

Slide 62

Slide 62 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 63

Slide 63 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 64

Slide 64 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 65

Slide 65 text

@michieltcs #StandWithUkraine TRACKING EVENTS EVENT EVENT EVENT EVENT EVENT EVENT . . . . . . . . . . . . . . EVENT EVENT EVENT

Slide 66

Slide 66 text

@michieltcs #StandWithUkraine TRACKING EVENT PROCESSOR GET NEXT EVENT APPLY TO NEW PROJECTION LAST EVENT? USE PROJECTION yes no

Slide 67

Slide 67 text

@michieltcs #StandWithUkraine TRACKING EVENT PROCESSOR @Target(AnnotationTarget.CLASS) @Retention(AnnotationRetention.RUNTIME) annotation class RebuildableProjection( val version: String = "", val rebuild: Boolean = false )

Slide 68

Slide 68 text

@michieltcs #StandWithUkraine TRACKING EVENT PROCESSOR @Autowired fun startTrackingProjections(configurer: EventProcessingConfigurer) { val scanner = ClassPathScanningCandidateComponentProvider(false) scanner.addIncludeFilter(AnnotationTypeFilter(RebuildableProjection::class.java)) for (bd in scanner.findCandidateComponents("org.demo")) { val projectionClass = Class.forName(bd.beanClassName) val rebuildableProjection = projectionClass.getAnnotation(RebuildableProjection::class.java) if (rebuildableProjection.rebuild) { registerRebuildableProjection( configurer, projectionClass, rebuildableProjection) } } }

Slide 69

Slide 69 text

@michieltcs #StandWithUkraine TRACKING EVENT PROCESSOR private fun registerRebuildableProjection(configurer: EventProcessingConfigurer, projectionClass: Class<*>, rebuildableProjection: RebuildableProjection) { val processingGroup = projectionClass.getAnnotation(ProcessingGroup::class.java) val name = processingGroup?.let(ProcessingGroup::value) ?: (projectionClass.name + "/" + rebuildableProjection.version) configurer.assignHandlerTypesMatching(name) { eventHandler -> projectionClass.isAssignableFrom(ClassUtils.getUserClass(eventHandler)) } configurer.registerTrackingEventProcessor(name) }

Slide 70

Slide 70 text

@michieltcs #StandWithUkraine TRACKING EVENT PROCESSOR trackingEventProcessor.shutDown() trackingEventProcessor.resetTokens() trackingEventProcessor.start()

Slide 71

Slide 71 text

@michieltcs #StandWithUkraine TRACKING EVENT PROCESSOR class BankAccountProjections { private val activeAccounts: MutableMap = HashMap() @ResetHandler fun resetProjections() { activeAccounts.clear() } ////
 }

Slide 72

Slide 72 text

@michieltcs #StandWithUkraine EVENT VERSIONING

Slide 73

Slide 73 text

@michieltcs #StandWithUkraine NEW BUSINESS REQUIREMENTS

Slide 74

Slide 74 text

@michieltcs #StandWithUkraine CHANGING VIEW ON EVENTS

Slide 75

Slide 75 text

@michieltcs #StandWithUkraine IRRELEVANT

Slide 76

Slide 76 text

@michieltcs #StandWithUkraine DIFFERENT FIELDS

Slide 77

Slide 77 text

@michieltcs #StandWithUkraine WRONG NAME

Slide 78

Slide 78 text

@michieltcs #StandWithUkraine TOO COARSE

Slide 79

Slide 79 text

@michieltcs #StandWithUkraine TOO FINE

Slide 80

Slide 80 text

@michieltcs #StandWithUkraine HOW TO SUPPORT YOUR LEGACY?

Slide 81

Slide 81 text

@michieltcs #StandWithUkraine Commands can be renamed 1

Slide 82

Slide 82 text

@michieltcs #StandWithUkraine Commands can be renamed 1 Events are immutable 2

Slide 83

Slide 83 text

@michieltcs #StandWithUkraine Commands can be renamed 1 Events are immutable Correct old events with new events 2 3

Slide 84

Slide 84 text

@michieltcs #StandWithUkraine Ledger Entry Aug 14 Inventory € 15600,00 Accounts Payable € 15600,00

Slide 85

Slide 85 text

@michieltcs #StandWithUkraine @michieltcs Ledger Entry Aug 14 Inventory € 15600,00 Accounts Payable € 15600,00 Ledger Entry Aug 14 Inventory € 16500,00 Accounts Payable € 16500,00

Slide 86

Slide 86 text

@michieltcs #StandWithUkraine Ledger Entry Aug 14 Inventory € 15600,00 Accounts Payable € 15600,00 Ledger Entry Aug 14 Inventory € 16500,00 Accounts Payable € 16500,00 Ledger Correction Entry Aug 14 Inventory € 900,00 Accounts Payable € 900,00

Slide 87

Slide 87 text

@michieltcs #StandWithUkraine COMPENSATING ACTIONS class MoneyWithdrawn {
 String accountId;
 BigDecimal amount;
 } class WithdrawalRolledBack {
 String accountId;
 BigDecimal amount;
 } Typo: too much withdrawn!

Slide 88

Slide 88 text

@michieltcs #StandWithUkraine COMPENSATING ACTIONS class AccountOpened {
 String accountId;
 String accountNumber;
 } class DuplicateAccountClosed {
 String accountId;
 } Duplicate account number!

Slide 89

Slide 89 text

@michieltcs #StandWithUkraine UPCASTING

Slide 90

Slide 90 text

@michieltcs #StandWithUkraine UPCASTING EVENT STORE OLD EVENT TYPE UPCASTER NEW EVENT TYPE EVENT HANDLER

Slide 91

Slide 91 text

@michieltcs #StandWithUkraine UPCASTING EVENT STORE

Slide 92

Slide 92 text

@michieltcs #StandWithUkraine UPCASTING @Revision("1.0") data class AccountOpened( val accountId: String, val accountNumber: String )

Slide 93

Slide 93 text

@michieltcs #StandWithUkraine UPCASTING 
 80f49161 
 12345678

Slide 94

Slide 94 text

@michieltcs #StandWithUkraine UPCASTING EVENT STORE ACCOUNTOPENED (1.0) EVENT HANDLER

Slide 95

Slide 95 text

@michieltcs #StandWithUkraine UPCASTING @Revision("2.0") data class AccountOpened( val accountId: String, val accountNumberIban: String )

Slide 96

Slide 96 text

@michieltcs #StandWithUkraine UPCASTING 
 80f49161 
 NL00ABNA012345678 


Slide 97

Slide 97 text

@michieltcs #StandWithUkraine UPCASTING EVENT STORE ACCOUNTOPENED (1.0) UPCASTER ACCOUNTOPENED (2.0) EVENT HANDLER

Slide 98

Slide 98 text

@michieltcs #StandWithUkraine UPCASTING class AccountOpenedUpcaster : SingleEventUpcaster() { private val typeConsumed = SimpleSerializedType("AccountOpened", "1.0") private val typeProduced = SimpleSerializedType("AccountOpened", "2.0") override fun canUpcast(intermediateRepresentation: IntermediateEventRepresentation): Boolean { return intermediateRepresentation.type == typeConsumed } override fun doUpcast(intermediateRepresentation: IntermediateEventRepresentation): IntermediateEventRepresentation { return intermediateRepresentation.upcastPayload( typeProduced, JsonNode::class.java ) { event: JsonNode -> val node = event as ObjectNode val accountNumber = node["accountNumber"].asText() node.put("accountNumberIban", toIban(accountNumber)) node.remove("accountNumber") event } }

Slide 99

Slide 99 text

@michieltcs #StandWithUkraine VERSIONED EVENT STORE

Slide 100

Slide 100 text

@michieltcs #StandWithUkraine events_v1 [
 {
 "id": "12345678",
 "type": "AccountOpened",
 "aggregateType": "Account",
 "aggregateIdentifier": "1234",
 "sequenceNumber": 0,
 "payloadRevision": "1.0",
 "payload": { ... },
 "timestamp": ...
 ...
 },
 ...
 ]

Slide 101

Slide 101 text

@michieltcs #StandWithUkraine COPY & REPLACE

Slide 102

Slide 102 text

@michieltcs #StandWithUkraine VERSIONED EVENT STORE LOOP OVER EXISTING EVENTS APPLY UPCASTER ADD QUEUED EVENTS USE NEW EVENT STORE NEW EVENTS QUEUE

Slide 103

Slide 103 text

@michieltcs #StandWithUkraine events_v2 [
 {
 "id": "12345678",
 "type": "AccountOpened",
 "aggregateType": "Account",
 "aggregateIdentifier": "1234",
 "sequenceNumber": 0,
 "payloadRevision": "2.0",
 "payload": { ... },
 "timestamp": ...
 ...
 },
 ...
 ]

Slide 104

Slide 104 text

@michieltcs #StandWithUkraine GDPR

Slide 105

Slide 105 text

@michieltcs #StandWithUkraine "RIGHT TO ERASURE"

Slide 106

Slide 106 text

@michieltcs #StandWithUkraine - G D P R , A RT I C L E 17 "... shall have the right to obtain ... the erasure of personal data concerning him or her without undue delay"

Slide 107

Slide 107 text

@michieltcs #StandWithUkraine PERSONALLY IDENTIFIABLE INFORMATION

Slide 108

Slide 108 text

@michieltcs #StandWithUkraine REMOVED

Slide 109

Slide 109 text

@michieltcs #StandWithUkraine ANONYMIZED?

Slide 110

Slide 110 text

@michieltcs #StandWithUkraine PROCESSING GDPR ART. 17 REQUESTS RIGHTTOERASUREINVOKED REMOVE FROM EVENT STORE REMOVE FROM READ MODELS NOTIFY 3RD PARTIES

Slide 111

Slide 111 text

@michieltcs #StandWithUkraine PROCESSING GDPR ART. 17 REQUESTS RIGHTTOERASUREINVOKED REMOVE FROM EVENT STORE ? REMOVE FROM READ MODELS NOTIFY 3RD PARTIES

Slide 112

Slide 112 text

@michieltcs #StandWithUkraine IMMUTABLE EVENTS?

Slide 113

Slide 113 text

@michieltcs #StandWithUkraine MODIFY DIRECTLY

Slide 114

Slide 114 text

@michieltcs #StandWithUkraine COPY WITH FILTER

Slide 115

Slide 115 text

@michieltcs #StandWithUkraine STORE PII EXTERNALLY

Slide 116

Slide 116 text

@michieltcs #StandWithUkraine STORE PII EXTERNALLY ACCOUNTOPENED EXTERNAL STORAGE Account Id Account number Name 1234 12345678 John Doe ... ... ... data class AccountOpened( @TargetAggregateIdentifier
 val accountId: String )

Slide 117

Slide 117 text

@michieltcs #StandWithUkraine CRYPTO SHEDDING

Slide 118

Slide 118 text

@michieltcs #StandWithUkraine ENCRYPTING EVENTS 
 80f49161 
 NL00ABNA012345678 
 Foo 
 Bar ... 


Slide 119

Slide 119 text

@michieltcs #StandWithUkraine ENCRYPTING EVENTS 
 80f49161 
 2dqjHkY8Mc8+cek4vs/9hzgkob4J3fZJNIJh2sAXlJ0= accountNumberIban> 
 N5Y27vd0UbKo6FIu5c7QGQ== 
 OSKrzfuuuayuUNXYS5YUug== ... 


Slide 120

Slide 120 text

@michieltcs #StandWithUkraine ENCRYPTING EVENTS GENERATE EVENT FIND / CREATE ENCRYPTION KEY ENCRYPT PAYLOAD VALUES STORE 
 EVENT

Slide 121

Slide 121 text

@michieltcs #StandWithUkraine DECRYPTING EVENTS LOAD 
 EVENT FIND ASSOCIATEDENC RYPTION KEY DECRYPT PAYLOAD VALUES PROCESS 
 EVENT

Slide 122

Slide 122 text

@michieltcs #StandWithUkraine SHEDDING THE KEY LOAD 
 EVENT FIND ASSOCIATEDENC RYPTION KEY DECRYPT PAYLOAD VALUES PROCESS 
 EVENT X

Slide 123

Slide 123 text

@michieltcs #StandWithUkraine OPTIONS https://developer.axoniq.io/axon-data-protection/overview https://github.com/everest-engineering/axon-crypto-shredding-extension

Slide 124

Slide 124 text

@michieltcs #StandWithUkraine CLOSING WORDS

Slide 125

Slide 125 text

@michieltcs #StandWithUkraine NO SILVER BULLET

Slide 126

Slide 126 text

@michieltcs #StandWithUkraine LOTS OF CHALLENGES

Slide 127

Slide 127 text

@michieltcs #StandWithUkraine (IM)MUTABILITY

Slide 128

Slide 128 text

@michieltcs #StandWithUkraine AUDIT TRAIL

Slide 129

Slide 129 text

@michieltcs #StandWithUkraine SCALABILITY

Slide 130

Slide 130 text

@michieltcs #StandWithUkraine TESTING

Slide 131

Slide 131 text

@michieltcs @michieltcs #StandWithUkraine THANK YOU FOR LISTENING! twitter: @michieltcs 
 mastodon: @[email protected] 
 email: [email protected] www.michielrook.nl