Technical Business Analyst
Fixed-income trades to ISO 20022
Helped design and deliver the back-office payment workflow that carried ICI trade information through to pacs.009 instructions on the bank's settlement infrastructure, replacing spreadsheet tracking and saving 40 hours of manual work a week.
Seven systems, one payment
ICI, IBM MQ, GMTC, CRD, Kafka, Payment Prep and downstream settlement, specified at the level of fields, events and lifecycle states rather than screens.
Requirements as an implementation contract
Not “the user should be able to net the payment”, but which states qualify, what the Kafka payload carries, what PPS returns, and what the UI shows when one record fails validation.
A defect traced three systems upstream
Inconsistent CRD settlement data surfaced only as PPS validation failures. I traced it back to the source, documented the expected behaviour and drove the remediation.
A regression package that outlived the project
A reusable set of scenarios covering the critical behaviours of the workflow, so future changes could be checked against them after the original team moved on.
Delivered, not just specified
The deployment runbook, the release approvals, go-live sequencing, production sanity testing with controlled payments, and production support afterwards.
Before moving into a Software Engineer role at BMO Capital Markets, I worked as a technical business analyst within Capital Markets Payments and FX Derivatives Technology.
My primary project involved helping design and deliver a new ISO 20022-compliant back-office payment-processing workflow for ICI, a fixed-income trading system used by front-office users.
Although my official title was Business Analyst, the role was highly technical. I worked at the intersection of business requirements, distributed-system design, data normalization, message integration, payment processing, software delivery, testing, release management, and production support. My responsibility was not simply to document what users wanted. I needed to understand how a front-office trading process should translate into a working technical solution spanning:
I worked directly with front-office users, back-office operations, developers, application owners, and infrastructure teams to understand the existing process, define the future-state workflow, translate that workflow into technical requirements, validate the implementation, and help take the solution into production.
The problem we were solving
The ICI fixed-income workflow relied heavily on older processes and manual tracking. Front-office users were maintaining significant portions of the trade and payment information through spreadsheets and legacy workflows, which created operational overhead and made it difficult to provide a standardized payment-processing experience comparable to newer Capital Markets platforms. All told, that manual work cost about 40 hours a week.
The objective was to introduce a more structured workflow where ICI trade information could move automatically into BMO's back-office payment infrastructure, supporting the entire lifecycle of a payment:
The solution therefore required much more than creating a new UI. We had to define how the underlying systems would communicate, how payment records would be represented, which application owned each part of the workflow, how users would interact with the payment lifecycle, and how state changes would propagate between the UI and backend systems.
Requirements elicitation with front office and operations
A major part of my role was working directly with the people who would actually use the system. We held recurring requirements sessions with internal business stakeholders, including:
- ICI front-office users responsible for booking fixed-income trades
- back-office and operational users responsible for payment processing
- application owners
- developers
- other business analysts and technical stakeholders
These conversations were used to understand both the existing workflow and the desired future state. We discussed what information should arrive from ICI, which payment fields users should be able to see and edit, when a payment should require manual intervention, how incomplete payments should be presented, when a payment becomes eligible for netting, which payments can be combined, what should happen when settlement instructions change, who is allowed to perform each action, what approval controls are required, what the UI should display after each lifecycle transition, and what backend event should occur when a user takes an action.
This required translating business terminology and operational procedures into behaviour that developers could actually implement.
Business and technical requirements documentation
The requirements gathered from stakeholders were formalized into the project's requirements documentation, including the BRD and detailed requirements artifacts used by the team. I helped define both the functional requirements and the technical behaviour required to support them, covering:
- payment ingestion
- data normalization
- payment lifecycle states
- UI behaviour
- settlement-instruction handling
- amendment workflows
- payment netting
- approval workflows
- user permissions
- Kafka message contracts
- backend processing behaviour
- validation requirements
- error scenarios
- downstream responses
- acceptance criteria
Because I had a software-engineering background, I approached requirements at a much lower level than writing statements such as “the user should be able to net the payment.” I needed to define what that actually meant technically: which payment states are eligible for netting, what happens when the user selects multiple payments, what criteria determine whether those payments can be grouped, what message GMTC publishes, which fields are included in that Kafka payload, what Payment Prep should do after receiving it, what database state should be updated, what response should be returned, what the UI should display when the operation succeeds, and what happens if one of the records fails validation.
This allowed the requirements to function as an implementation contract between the business process and the engineering team.
JIRA stories and developer handoff
I regularly translated larger business requirements into actionable JIRA stories and technical tickets. A typical ticket could include:
- user story
- business and technical context
- current behaviour and expected behaviour
- functional requirements and technical constraints
- message examples and data mappings
- edge cases, validation rules and failure scenarios
- acceptance criteria and test cases
- reproduction steps for defects
The objective was to provide enough information that a developer could understand not only what needed to change, but why, where the relevant data came from, what downstream systems depended on it, and how we would determine whether the implementation was correct.
I worked closely with developers throughout each sprint rather than handing requirements over and waiting for completion. We regularly discussed implementation questions, ambiguities, edge cases, and changes in business requirements during development, which made the role an active bridge between business stakeholders and engineers.
ICI to GMTC integration through IBM MQ
The first major system boundary in the new architecture was between ICI and GMTC. ICI produced the trade information required by the downstream payment workflow, collected into a structured CSV-based feed containing the fields required to identify and process the payment: sub-account information, payment amount, booking information, legal entity and booking location, trade-related identifiers, and the payment attributes required downstream.
Rather than GMTC receiving this information through a synchronous REST API, the systems communicated through IBM MQ. ICI placed the feed onto the configured MQ infrastructure and GMTC periodically retrieved the available messages, creating a queue-based integration in which the source system and receiving application remained decoupled.
From a BA perspective, defining this integration meant understanding much more than “ICI sends GMTC a file”. We needed to understand:
- the structure of the source payload
- the transport mechanism and polling behaviour
- message headers and encoding
- the expected file and message format
- failure conditions
- what GMTC considered a valid record
- what happened when a field was missing or malformed
- how the source data mapped into GMTC's internal model
That work gave me hands-on exposure to IBM MQ, asynchronous integration, message structures, encoding issues, and enterprise middleware.
Feed Hub and data normalization
Once ICI data entered GMTC, it first passed through GMTC's Feed Hub, the ingestion point for the source data. From there, GMTC normalized the source-specific ICI representation into the internal data model used by the payment workflow.
This was an important architectural concept because GMTC handled more than one upstream trading platform. Each source system could represent information differently, but downstream payment services should not need to understand every source system's native structure, so GMTC acted as a normalization layer: a source-specific ICI representation became a normalized GMTC payment representation.
I helped analyze and configure these mappings at the field level. For each field we needed to understand what the source field means, where it belongs in GMTC, whether transformation is required, whether it can be null, whether it is mandatory, whether it is used for matching, whether another system eventually depends on it, whether the UI should expose it, and what happens if the value is invalid.
This gave me practical experience with data lineage, canonical models, mapping rules, and data contracts between distributed systems.
Settlement instructions and CRD
Payment data from ICI alone was not always sufficient to construct the final payment. The system also required settlement instructions, or SSIs. BMO's Client Reference Data platform, CRD, acted as the authoritative source for the client's settlement information, so the architecture needed to connect ICI payment information with the appropriate CRD SSI data before the payment could progress.
I contributed to defining how this information should be represented and matched inside GMTC, working with SSI JSON structures, payment identifiers, mapping rules, matching logic, and the relationships between ICI payments and CRD records. That included transformation structures over collections such as impPaymentIds, iciPaymentIds and paymentActions, and mapping operations over JSON arrays such as evalAsJSON(), toSet() and toList().
The important part was not the individual expression. It was understanding the data relationship that expression represented, and ensuring the correct settlement instructions were associated with the correct payments before the downstream flow continued.
Payment Prep as the backend processing engine
Although GMTC contained the workflow and user interface, many of the actual payment operations were performed by the backend Payment Preparation Service. GMTC and PPS communicated primarily through Kafka, which meant actions performed through the GMTC UI did not translate into synchronous REST requests. Instead, user actions generated structured JSON events published to Kafka; PPS consumed those events, performed the required business logic, updated the payment state, and published a response that GMTC consumed to update its own database and UI.
This event-driven architecture mattered because the UI represented business state that ultimately depended on asynchronous backend processing. As a BA, I had to define both sides of these interactions: what action the user takes, what message GMTC sends, what fields belong in the payload, how PPS should interpret the action, what business logic should run, what status PPS should return, how GMTC should respond to that result, and what the user should see afterwards.
Payment lifecycle design
One of the most important parts of the project was defining the payment lifecycle. Rather than representing payments as simply complete or incomplete, the workflow used business states that represented what could happen next.
A payment entered To Be Amended when PPS determined that it did not contain sufficient information to continue processing, for example when the required settlement instructions were incomplete. The payment remained visible within GMTC so the appropriate business user could correct the underlying information.
If the payment contained all required information and passed the required checks, PPS returned a response indicating that the payment was To Be Netted, meaning the record was now eligible to move into the next stage of the workflow. The status itself therefore represented business meaning, not just application state.
Amendment and the CRD update loop
A particularly important requirement involved payments that could not initially proceed because settlement information was incomplete. The business user could access the appropriate CRD functionality and update the client's settlement instructions. Once the updated SSI information propagated back into GMTC, the corresponding information was sent back through the payment-processing workflow and PPS re-evaluated the payments waiting for amendment. If the updated SSI now contained everything required, PPS returned a new status moving the payment to To Be Netted; if not, the payment stayed where it was.
Defining this workflow required understanding how a human correction performed in one application should cause state transitions across several other systems.
Payment netting
Once payments reached To Be Netted, users could begin the netting process. Netting allows multiple eligible payment obligations to be consolidated when they share the appropriate settlement characteristics: if several payments had compatible settlement instructions, they could be combined into a single resulting payment instead of being processed independently. The workflow also needed to support the case where only one payment existed for a particular settlement grouping, where the user could still move the individual payment through the netting stage.
When the user initiated the netting action in GMTC, another Kafka event was generated and sent to PPS, which performed the associated backend processing and returned the result. GMTC then updated the payment state and moved the resulting payment into the next stage. This required defining:
- eligibility rules
- grouping behaviour
- UI selection behaviour
- backend action types
- Kafka payload contents
- the expected PPS response
- database updates
- error behaviour
- the resulting payment state
Four-eyes approval control
Once a payment had been successfully netted, it could not immediately be released. The workflow incorporated a four-eyes control, a common control within financial systems requiring a second individual to independently review and approve an action. The person who prepared or netted the payment could not complete the entire process alone; another authorized user needed to review the payment details in GMTC and approve the transaction.
That added both a business requirement and an access-control requirement, so we had to define:
- which users could net payments
- which users could approve them
- what permissions applied to each role
- what information reviewers needed to see
- which actions were enabled at each state
- what should happen when approval was submitted
- what audit and state information should be retained
Payment release and ISO 20022 generation
After the four-eyes approval was completed, GMTC generated another payment action and sent it to PPS through Kafka. PPS then performed the release processing, using the normalized payment data and settlement information to generate the appropriate ISO 20022 payment instruction, including the pacs.009 message used for the relevant financial-institution credit-transfer flow. The payment was then released into the downstream payment infrastructure, and PPS sent a response back to GMTC confirming the new status.
The end-to-end workflow I helped define therefore connected front-office fixed-income trade information to an ISO 20022-compliant payment instruction capable of being sent through the bank's settlement infrastructure. The wider project was part of BMO Capital Markets' ISO 20022 modernization effort, with PPS acting as one of the final internal stages responsible for constructing compliant MX payment messages.
ACK, NACK and downstream status propagation
The workflow did not end once a payment was released. Downstream payment systems could return acknowledgements, negative acknowledgements, or rejection information, and those statuses needed to propagate back upstream so users could determine what happened to the payment after release.
The response travelled back through the architecture and ultimately updated GMTC, giving business and operational users visibility into whether the payment was accepted, was rejected, failed validation, or was still progressing through downstream processing. The GMTC UI therefore acted as more than an input interface: it became an operational view into the payment's lifecycle.
UI and UX requirements
A major component of my BA work involved defining how this fairly complicated distributed workflow should appear to a business user. Front-office and back-office users should not need to understand Kafka topics, IBM MQ, JSON contracts, data normalization, or Payment Prep internals just to process a payment, so the UI needed to translate the distributed backend state into something understandable. I worked with stakeholders to define:
- screen layouts and payment tables
- displayed fields
- available actions
- workflow states
- filtering behaviour
- amendment and netting interactions
- approval behaviour
- user permissions
- error messages and status presentation
This required thinking about UX and system state at the same time. A button could not simply exist because a user wanted it: the button needed to correspond to a valid backend action at that particular point in the payment lifecycle.
User roles and permissions
I also worked on defining and configuring user permissions within GMTC. Because the system handled financial transactions, not every user could perform every action, and the four-eyes approval process meant the system had to enforce separation of duties. That required defining user roles, permitted and restricted actions, approval capabilities, visibility rules, and state-dependent controls, and translating those business-control requirements into behaviour that could be implemented and tested technically.
A testing strategy across three environments
Testing was a significant part of the role because the solution spanned multiple applications, asynchronous messaging interfaces, backend services, and user-facing workflows. My responsibility was not limited to verifying that an individual JIRA ticket appeared to work: I helped validate that the complete business process continued to behave correctly across GMTC, PPS, CRD, IBM MQ, Kafka, and the downstream payment infrastructure.
GMTC was deployed across development, QA and production. Development was where I first reviewed newly implemented functionality, particularly UI and workflow changes: page behaviour, payment tables, displayed fields, button availability, workflow transitions, validation messages, permissions, amendment, netting, approval controls and state-dependent actions. Catching functional or UX issues there kept them out of integration testing.
QA was where the more extensive backend and integration testing occurred, because clicking a button in GMTC was only the beginning of the actual workflow:
Testing only the screen would not have been enough. I needed to validate that the business action shown in GMTC was actually producing the correct backend behaviour within PPS.
System integration testing
SIT focused on verifying that independently developed systems worked correctly once they were connected. Because the solution crossed several system boundaries, this often meant following a payment through a significant portion of the architecture, preparing or coordinating test data, initiating scenarios, monitoring application behaviour, inspecting messages, and comparing actual results against the requirements.
Depending on the scenario, I would inspect:
- CSV source records
- IBM MQ messages
- JSON payloads and XML messages
- Kafka requests and responses
- database state
- GMTC UI state
- PPS processing results
- ACK and NACK responses
- downstream payment statuses
That let me validate the system at multiple layers rather than treating the UI as the only source of truth. It is also where a software-engineering background was most valuable: I could move between the business-facing UI and the underlying technical messages instead of treating the application as a black box.
End-to-end business workflow testing
A major focus was ensuring the complete ICI payment lifecycle worked. I tested payments that arrived with all required information and should move directly to To Be Netted, and negative scenarios where information was missing and PPS should return To Be Amended instead. From there I could validate the amendment loop, then the business actions that follow it: netting eligible payments, netting a single payment, grouping compatible payments, performing the four-eyes approval, enforcing user permissions, releasing an approved payment, verifying resulting states, validating downstream acknowledgements, and handling rejection paths.
The objective was to test the workflow as an actual business user would experience it while simultaneously validating the underlying system interactions.
Story-level testing against acceptance criteria
I validated individual development stories once developers completed their implementation, with the acceptance criteria written during requirements analysis as the basis. For a story introducing netting, that could mean testing valid multiple-payment netting, valid single-payment netting, incompatible payments, missing settlement information, an invalid payment state, an unauthorized user, an unexpected PPS response, and a backend processing failure.
If the behaviour did not match the requirement, I documented the issue and worked directly with the developer to determine whether the cause was implementation logic, mapping configuration, data, environment configuration, an integration problem, or ambiguity in the original requirement. That feedback loop between requirements, development, testing and refinement ran continuously throughout the project.
Regression testing
As the system matured, testing only newly developed functionality was no longer sufficient: because GMTC and PPS supported complex workflows and multiple upstream systems, even a small change could introduce unintended side effects several stages downstream. I retested critical existing functionality after changes:
- payment ingestion
- data normalization
- SSI enrichment
- payment-state determination
- To Be Amended and To Be Netted processing
- amendment workflows
- netting
- four-eyes approval
- payment release
- user permissions
- PPS integration and Kafka request and response handling
- lifecycle updates and downstream acknowledgement handling
A regression package that outlived the project
One of the testing deliverables I created was a formal regression test package for the ICI workflow. The objective was not simply to test the system during the initial implementation; I wanted the team to have a repeatable framework that could continue to be used after delivery, so that future BAs, developers and testers could execute it whenever changes were introduced.
Each scenario captured:
- the functionality being tested
- test prerequisites and required test data
- the starting payment state
- the user action
- expected GMTC behaviour
- expected PPS behaviour
- the expected Kafka interaction
- the expected lifecycle transition and UI state
- the expected result and pass or fail outcome
The package became a reusable baseline: these are the critical behaviours that must continue to work regardless of what future changes are introduced. If someone later modified the normalization logic, the package could be executed to confirm that amendment, netting, approval and release still worked; if a change was made to PPS, it could verify that GMTC still received and interpreted the expected backend responses. It converted knowledge that would otherwise have lived only inside the original project team into a repeatable asset.
It also did not focus exclusively on the happy path. Financial systems need predictable behaviour when something goes wrong, so scenarios covered missing information, incomplete settlement instructions, mappings producing unexpected values, PPS rejecting a payment, invalid user actions, missing permissions, wrong lifecycle states, and downstream failures. A successful system is not one that simply processes valid payments. It also has to fail correctly: return the appropriate status, keep the payment in the correct state, prevent invalid actions, and tell users enough to understand what happened.
User acceptance testing
SIT answers whether the systems work together correctly. UAT answers whether the solution actually works for the people who need to use it, which mattered here because we were replacing an existing business process for real front-office and back-office users.
During UAT the business clients executed realistic scenarios based on their day-to-day workflows, and my role included maintaining regular communication with them while they did: explaining functionality, clarifying expected behaviour, communicating known constraints, understanding and reproducing the issues they hit, determining whether feedback represented a defect or a new requirement, communicating issues back to developers, tracking outstanding items, and coordinating retesting after fixes.
Because I had participated in the original requirements discussions, I could connect UAT feedback directly back to the business intent. When a client said something did not behave the way they expected, I could evaluate that against the agreed requirements, inspect the actual system behaviour, and determine whether it was a defect, a misunderstood requirement, a UI issue, an integration problem, an environment issue, or a new requirement that needed to be scoped separately.
From requirement to acceptance
One aspect of the role I found particularly valuable was participating in almost the complete validation lifecycle:
That taught me that quality assurance in an enterprise system is not a single phase at the end of development. It is a continuous process of validating that the original business requirement survives every layer between what the client asked for and what ultimately runs in production.
Integration troubleshooting below the application layer
Working on the ICI integration also exposed me to lower-level middleware issues. Not every integration failure was caused by incorrect business data. We encountered issues related to message headers, encoding, byte representations, US-ASCII handling, queue configuration, MQ message formats, targetclient=1, and receiving-system behaviour.
That taught me that distributed integration problems often exist below the application layer. A payload can contain the correct business information and still fail because the receiving application interprets the transport, encoding, header, or wrapper differently. Understanding these issues made me significantly stronger at troubleshooting enterprise integrations.
Defect investigation and root-cause analysis
One of my most important contributions was discovering a significant inconsistency in the SSI information produced by CRD. The issue was not immediately obvious because the failure appeared downstream: incorrect or inconsistently populated CRD data propagated through CRD, then GMTC, then PPS, and eventually caused PPS validation failures.
Instead of treating the downstream failure as an isolated PPS defect, I traced the data backwards through the architecture to determine where the incorrect value originated. I helped:
- identify the source of the inconsistency
- understand how it propagated across systems
- document the expected behaviour
- determine what CRD needed to change
- identify downstream validation considerations
- create remediation JIRA tickets
- coordinate with the relevant teams
- correct affected records and retest the complete flow
That experience significantly improved my understanding of data lineage and root-cause analysis in distributed systems. A failure in one application may actually originate several systems upstream.
Release planning and the deployment runbook
My responsibilities extended beyond requirements and testing into release delivery, and I took a leading role in preparing for the production rollout. One of the major artifacts I helped create was the deployment runbook. Because the release involved several dependent applications, the production deployment could not be treated as a single application release: it coordinated changes across ICI, CRD, GMTC, PPS, messaging infrastructure and environment configuration.
The runbook documented the required sequence of activities, prerequisites, responsibilities, validation steps, and post-deployment checks. I needed to understand which application has to deploy first, what configuration must exist beforehand, whether the MQ and Kafka dependencies are ready, whether CRD contains the required data, whether GMTC mappings are deployed, whether PPS is ready to process the resulting payload, who owns each deployment action, what blocks the next step, and how we validate success.
That gave me experience thinking about software delivery as a coordinated system change rather than a code deployment. I also helped create and coordinate Application Release Approvals and the associated deployment documentation, which meant considering approvals, testing evidence, change documentation, implementation sequencing, operational risk, dependencies, rollback, ownership and auditability. Delivering enterprise software requires both engineering and disciplined change management.
Go-live and production sanity testing
I participated directly in the production go-live. During the deployment window we followed the runbook and coordinated across the teams responsible for the different applications. Afterwards I participated in production sanity testing using controlled test payments, following them across the architecture and verifying that GMTC received the source information, CRD information was available, the correct SSI was associated with the payment, normalization worked, the correct downstream structure was created, PPS accepted the payment, expected validations passed, routing worked, and statuses propagated as expected.
The distinction matters: a successful deployment is not the same thing as a successful business transaction. Production sanity testing verified the second one.
Production support
After release I continued supporting the payment-processing ecosystem in production, covering the ICI workflow as well as other ISO 20022 flows involving systems such as Calypso and Falcon. When a payment failed, I helped trace it across system boundaries:
This involved analyzing XML, JSON, payment fields, reference data, mapping behaviour, message formatting, validation failures and ACK or NACK responses. I became comfortable reasoning backwards through a distributed architecture instead of assuming that the system where the error appeared was necessarily the system that caused it. The team was ultimately working toward better straight-through processing, where valid payments could move from trade capture through settlement with minimal manual intervention.
Working across business and engineering
The most valuable part of the role was learning to operate between two very different perspectives. A business user might describe a requirement as “when I fix the SSI, I want the payment to move out of amendment.” A developer needs something closer to: when updated SSI data is received, identify affected payments currently in the amendment state, publish the required processing event, revalidate the enriched payment in PPS, return the resulting lifecycle state, persist it in GMTC, and update the corresponding UI workflow.
My job was to understand both versions, which meant regularly asking what the JSON actually looks like, which field uniquely identifies this record, where that value originates, which application owns this state, what Kafka event represents this action, what happens if the value is null, what happens when CRD returns incomplete data, how PPS indicates failure, what GMTC should do with that response, what the user should see, how we reproduce the scenario, how we test the negative path, and what other systems the change could affect.
That technical depth is what allowed me to serve as a bridge between the people defining the business process and the people implementing the software.
Technologies and concepts
Business analysis
- requirements elicitation
- functional and technical requirements
- BRDs and detailed requirements documentation
- stakeholder interviews
- process modelling
- user stories and acceptance criteria
- JIRA
- edge-case analysis
- test-case design
- defect management
Distributed systems
- event-driven architecture
- asynchronous processing
- IBM MQ
- Apache Kafka
- queue-based integrations
- message contracts
- JSON, XML and CSV
- data lineage
- upstream and downstream dependencies
- failure propagation
Data and integration
- data normalization
- mapping rules
- canonical data models
- SSI matching
- data enrichment
- field-level and schema analysis
- message transformation
- reference-data integration
Payments
- fixed-income payment workflows
- settlement instructions
- CRD
- ISO 20022
- SWIFT
- pacs.009
- ACK and NACK processing
- payment lifecycle states
- netting
- four-eyes approval
- straight-through processing
Testing and delivery
- SIT and UAT
- regression testing
- end-to-end testing
- production sanity testing
- root-cause analysis
- defect triage
- deployment runbooks
- release coordination
- ARAs
- production support
What I actually owned
It would be inaccurate to describe the role as writing documentation while developers built the system, and equally inaccurate to claim I personally coded every component. The actual role sat between those two extremes: I took meaningful ownership over the technical analysis and delivery of the integration. I helped determine:
- what needed to be built
- how the business workflow should behave
- how systems should communicate
- what data needed to move between applications, and how it should be represented
- how user actions mapped to backend events
- what lifecycle states were required
- what developers needed to implement
- how the implementation should be tested
- how defects should be investigated
- how the release should be coordinated
- whether the completed solution actually worked end to end
Developers owned the production code within their respective applications, while I worked across the boundaries between those applications and helped drive the overall solution from requirements through production. That technical ownership is what distinguished this role from a traditional business analyst position.
What I took away from the role
This experience fundamentally changed how I understood software engineering. Before working at BMO, it was easy to think about an application as a codebase. Working on this project showed me that enterprise software is really a collection of systems, teams, data contracts, business processes, infrastructure, and operational controls that all have to work together. A single front-office payment could involve trade capture, MQ transport, normalization, reference-data enrichment, Kafka events, backend processing, approval controls, ISO 20022 generation, downstream settlement and a SWIFT response, and every part of that chain had its own owner, requirements, failure modes and dependencies.
It also showed me how valuable it is to understand both the business problem and the technical implementation. Being able to speak with a front-office user about how they wanted the workflow to behave and then immediately speak with a developer about Kafka payloads, JSON mappings, validation behaviour or system dependencies became one of my strongest skills.
That experience was also what pushed me toward software development. The deeper I got into the architecture, integration logic, mappings, testing and technical problem-solving, the more I wanted to participate directly in implementation, which eventually led me to move from business analyst work into a Software Engineer role within BMO Capital Markets.