Refactoring Applications Visually

Richard Keit

Principal Solution Architect

January 24, 2024

Part one of a two-part blog post on refactoring applications on AWS using event-driven architectures

This article assumes basic knowledge of some AWS services like AWS API Gateway and AWS Eventbridge — follow the embedded hyperlinks for further reading.

On-going maintenance, reduction of technical debt and introduction of new features in legacy monolith applications often can result in complex and high risk code changes. Refactoring applications in place requires concentrated effort to isolate changes to reduce the blast radius when deploying the changes.

Martin Fowler coined the term, Strangler Fig Application pattern, paraphrased to building a new functionality around an existing application — much like the Strangler Fig tree. This approach can mitigate some of the concerns by gradually introducing new functionality around the boundaries of the old system.

Event-driven architectures are conducive to the strangler pattern and have a range of benefits, including:

Flexibility & scalability — No steady-state compute — With actions being invoked as a result of events flowing through the system, in periods of reduced activity, the compute will not be invoked. Inversely, in periods of increased activity, the system will scale as required.

Fault tolerance — The design lends itself to modular components that can complete actions and fail independently, not creating a cascading set of failures.

Event Sourcing — As events are produced for actions within the system, it creates the ability to query related events via nominated correlation IDs.

In the first blog of a two-part series, we’ll explore how to refactor monolith applications. In the second blog, we’ll use the new AWS Application Composer service.

Dog Treat Customer Use Case

In our fictitious example, we have a Dog Treat company currently using an external invoice processing merchant. When an invoice is submitted to an external vendor, there is an established manual process to reconcile invoices from the vendor, which is incredibly inefficient.

Existing System Overview

The diagram below depicts the existing workflow between the application and the external processing merchant. The blue arrows show the interactions directly to the invoicing process conducted by the system. Conversely, the red arrows highlight manual processes required in the event of an unpaid invoice.

1Copy of the invoice is published to S3 for storageInternal – Application 
2An API request is made to external merchant endpoint with the location of the invoiceInternal – ApplicationAny issues with submitting the request to the mechant endpoint creates challenge for backend to retry request
3Merchant system pulls the invoice process internallyExternal – Processing Merchant 
4Through the monthly reconciliation process, if it’s identified that an invoice has not been paid – a finance analyst will contact the Processing Merchant to obtain details about the invoice.Finance AnalystCommunication can be email or telephone call.
Existing Architecture Flow

Updated System Overview

The diagram below references AWS services that may be new to some readers; has summarised services synonymise with event-driven architectures. Read more here and follow the embedded links for more detailed service documentation.

New Invoicing System Architecture

Using an event-driven approach to refactor the system, the changes are as follows:

1Copy of the invoice is published to S3 for storageInternal – ApplicationUnchanged
2Application emits an event to the eventbus that an invoice has been created and ready for processingInternal – ApplicationOnly change required to the original functionality
3Event Filter listening to the “Invoice Created” event detailInternal – InvoicingRich ability to filter events based on content patterns
4API Destination will send event to Merchant EndpointInternal – InvoicingAPI Destination will manage authentication (basic/oauth/api-key) and retries of the request.Input Transformers are used to change event to format required of destination
5Merchant system pulls the invoice process internallyExternal – Processing MerchantUnchanged
6Merchant sends status to Invoicing system via API requestExternal – Processing Merchant 
7API gateway publishes an “Invoice Processed” event to EventbusInternal – InvoicingEvent published and can be leveraged by any interested consumers.
No runtime needs to be created – direct integration example shown in API Gateway HTTP API to Amazon EventBridgeIf enrichment of request is required, example using VTL is shown in Capturing client events using Amazon API Gateway and Amazon EventBridge
8Event filter for the “Invoice Processed” event to complete business logicInternal – InvoicingIsolated functionality to update local records with status of invoice processing

Key Benefits of the New Architecture

  • Limited runtime code — The only required code is the business logic to update the internal database.
  • All other integration components are configurations of AWS-managed services, not requiring bespoke engineering.
  • Events are now consumable by interested parties — Other business units that are interested in the new “invoice” events can build functionality without the need to update the current process. Example use cases include analytics functionality of the invoicing process.

Additional Resources

The AWS Serverless Developer Advocacy team does a fantastic job of showcasing updates from AWS feature drops to community opensource tools; these are our favourite references:

Here are the links to some other resources that you might find useful — Event FilterContent Filtering PatternsAPI DestinationInput TransformersAPI Gateway HTTP API to Amazon EventBridge
VTLCapturing client events using Amazon API Gateway and Amazon EventBridge

Part two of this blog will go into more detail on the refactoring experience using the new AWS Application Composer service.


Great Tech-Spectations

Great Tech-Spectations

The Versent & AWS Great Tech-Spectations report explores how Aussies feel about tech in their everyday lives and how it measures up to expectations. Download the report now for a blueprint on how to meet consumer’s growing demands.