NAB-X: a microservice-like approach in the application experience space

National Australia Bank
11 min readSep 22, 2020

--

At NAB, microservices have been adopted broadly, and are a growing and evolving ecosystem. This has meant that data is unlocked to build new customer experiences, and duplication of server-side build effort across channels has been reduced.

This model also means that ‘Federated Delivery’ is possible, in that domain owners can release new versions of microservice functionality on an ongoing basis for platforms to consume.

While this provided a way forward on the server-side, we still had no roadmap for solving the same types of problems that arise from maintaining multiple monolithic frontend stacks.

This article outlines the NAB-X platform used for federated delivery of frontend capabilities at NAB.

Problems we aimed to solve

The primary driver was serving our customers by delivering the features they need more quickly — at reduced cost of delivery.

The following issues were targeted as key areas that needed to be addressed.

  1. Duplicated build effort across platforms and channels for the same feature
  2. Delivery bottlenecks in platform teams servicing multiple product domains
  3. UI and Accessibility inconsistency across channel platforms
  4. High risk monolithic frontend deployments

Taking each of these problems into account, we realised that decomposing our monolithic frontends into micro-frontends and allowing product domains to become more directly involved in delivery would be worth exploring.

Micro-frontends are similar in concept to micro-services, in that they are discretely deploy-able shared capabilities, however they deliver this concept to frontend user experience. Some background reading: https://micro-frontends.org/ · https://martinfowler.com/articles/micro-frontends.html

Monolith to Micro-frontend federation

Easy to say, not so simple to achieve.

New challenges

While this strategy appeared promising, there were also some new challenges to consider.

1. We needed to provide guardrails and patterns for teams to follow that would ensure a cohesive user experience, and compliant deployments.

2. We needed to provide tools to our teams to accelerate delivery of features, by removing the need to reinvent how to do basic, but time consuming, things such as authentication, structured logging and tracing, hosting pattern design and config management.

3. We needed to build a community around the tools and patterns in order to capitalise on the extensive cloud training that NAB had invested in, and the wealth of engineering experience that existed distributed across many teams around the organisation.

There were performance, integration and operating model aspects to be considered.

Prototype and socialise

There was enough interest in the micro-frontend concept to obtain executive sponsorship to prototype some key areas of interest and possible micro-frontend patterns. We ultimately settled on webcomponents as being the most viable approach for NAB.

Key drivers for this were:

1. Open, standards based and portable client-side integration.

2. Federated frontend hosting involved minimal resources.

3. No complex multi-domain concerns.

4. Clear integration boundary.

As we started to show various teams what was possible there was a high degree of interest, however it became clear that we would need to provide some boilerplate/templating in order to make it simpler to bootstrap new micro-frontends.

We also started to see that we would need some common standards and patterns to avoid fragmentation and ensure interoperability.

What do you mean ‘it is already in prod’?!

After creating a Yeoman generator for creating new miniapps, and the beginnings of an sdk/utility library to load them into any webpage, there was quite an explosion of prototype miniapps by a large number of teams who were clearly convinced it was a good solution.

The NAB-X project was formed to provide the tools, guidance and coordination we would need to be successful at scale.

The NAB-X Micro-frontend approach

Our implementation of micro-frontends (which we call ‘Miniapps’) uses W3C/WHATWG standards to deliver a framework agnostic integration layer for micro-frontends that implements a defined contract.

The key standards used are part of the WebComponents spec:

  • Custom Elements — used as the container of each miniapp
  • ShadowDOM — used to isolate styling of a given miniapp
  • HTML Templates — reusable templates used by the above

Read: https://developer.mozilla.org/en-US/docs/Web/Web_Components

Key Features and Principles

1. Discrete deployable applications, owned and operated by the teams that build them.

2. Insulation of miniapp frontends from backend api changes or platform differences.

3. Syndication of miniapps into multiple host applications regardless of miniapp hosting location.

4. Compatibility with ‘classic’ platforms, and with future frameworks.

5. Observability of the miniapp runtimes across host apps and clusters.

6. Versioning, with the ability to run multiple versions, allowing hosts apps to control adoption, or accept all updates.

7. Externalisation of authentication, authorisation and session management.

8. Reusability of miniapps across platforms, including UI consistency.

High level delivery approach used in NAB-X patterns

Miniapp deployments are containerised, and the Frontend and BFF are deployed and versioned as a single unit, to reflect the fact that they are intentionally tightly coupled to limit blast radius.

By using a simple platform agnostic tool such as Docker, we are able to easily evolve the hosting strategy over time, and not be limited to specific cloud providers.

Frontend
While we aim towards using pure web standard based engineering patterns, we currently make use of React within most Miniapp webcomponents. The exception is 3rd party integrations, which can also be wrapped in a Miniapp in order to be a part of the ecosystem.

Prototypes that use Vue and other frameworks have shown that we have an approach that can evolve over time with multiple generations of miniapps interacting with each other regardless of underlying technology.

For the webcomponent wrapper, we make use of Lit-Element from the polymer project which gives us a lightweight webcomponent interface with lifecycle management.

https://lit-element.polymer-project.org

Frontend code is hosted in small nginx docker containers allowing us to inject configuration at runtime, and keeping the door open to server-side rendering.

Webcomponent Custom Element and Shadow DOM of a Miniapp

Backend
Each Miniapp frontend generally has a paired BFF (backend-for-frontend) that is based on Apollo GraphQL (https://www.apollographql.com/). The BFF is deliberately tightly coupled to the Miniapp frontend and not shared at runtime. This allows teams building miniapps to optimise their backend to their specific frontend requirements, knowing that they are not affecting any other systems.

Each miniapp git repo consists of both the frontend and backend code. This is templated out for each new Miniapp via a Yeoman generator that provides a working starting point app, as well as integration with nab pipeline tools to deliver the miniapp in a compliant manner.

BFF code is hosted in Express Docker containers also fronted by nginx.

GraphQL Playground served from a Miniapp in development

Downstream services
The microservices downstream of the GraphQL BFF, are outside of the scope of NAB-X, however we have baked in api gateway token strategies based on the NAB Microservices ecosystem.

This allows teams to easily integrate with microservices without having to start from scratch.

A BFF could be your BFF

Frontend code can be complex and having to refactor it when updating apis creates overheads most teams would like to avoid. By using a BFF (Backend for For Frontend), we can ensure a stable api for our micro-frontend, and confine any changes related to apis to GraphQL datasources and resolvers which are generally simple and can be relatively uniform in structure.

We can also encapsulate context specific differences such as needing to route api calls via different network paths based on where a miniapp is used.

GraphQL advantages:

1. We can call multiple downstream rest apis in parallel and/or chained, and stitch the responses together reducing the number of rest calls from the frontend.

2. We can query for just the fields we need for the frontend. Some general-purpose rest apis return large datasets, and if we need only a couple of fields, we can save on bandwidth.

Mobile user experience in particular benefits from this.

A basic GraphQL REST Datasource class in Typescript

Are you sure we use Comic-Sans font here?

Most large organisations have a GEL or Global Experience Language, to standardise the way user experiences are designed, and ensure that teams stay on-brand. This can be a simple as fonts and colours, but generally also extends into the UI component behaviours that customers can expect when they interact with the organisation.

Having the GEL defined is useful, but more useful is an implementation of the GEL that is easily consumable by frontend engineers, and has the required Accessibility standards baked in.

For NAB-X miniapps, a React component library is maintained that implements the NAB GEL and has the appropriate oversight that helps deliver experiences that are accessible to all customers and bankers.

Miniapp teams still need to ensure they perform the appropriate subjective testing of their miniapps, but this raises the bar in terms of baseline accessibility, and UI consistency.

I’ve deployed my miniapp — now what?

Miniapps can be built, tested and deployed in isolation by product teams, but in order to be used by customers and bankers, they need to be integrated into a platform Shell.

The supplied security hardened infrastructure code and pipelines mean that miniapps are deployed using a standard model, which ensures that the way they are integrated into Shells is consistent. This typically involves configuration/code to load the miniapp webcomponent into the Shell.

Roles and responsibilities

Platform Shell teams are ultimately responsible for the channel they represent, and so we need clear contracts for miniapps to adhere to in order to be accepted and surfaced. Conversely, Shell teams do not necessarily have the knowledge required to perform in-depth functional testing of a given miniapp.

This means:

1. Non-functional stage gates are handled in a shared CI pipeline pattern in order for miniapps to be certified and added to the catalogue of available miniapps.

2. Miniapps teams are responsible for functional testing of the Miniapps they maintain, and also for any subjective shell integration testing.

3. Shell teams rely on health-check events emitted by miniapps to understand whether a given miniapp is working as expected in their shell.

4. Agreements such as SLAs and engagement processes between shell teams and miniapp teams need to be put in place early.

The team that maintains the nab-x tools endeavours to facilitate these engagements, by providing related sdk functionality, as well as documented guidance for teams adopting Federated delivery.

Migration pathways

As a transition plan towards removing monolithic frontends, miniapps can be surfaced in existing platforms alongside existing functionality. The risk here is that there will be a period where the worst of both worlds is in play — monolithic deployments, and also integration of miniapps into those platforms which requires coordinating across multiple teams.

This is something the NAB-X team are very conscious of, and so a reference shell that is optimised for miniapp delivery is being promoted to platform teams as the next stage of evolution.

The intent is that this shell will surface fragments of the existing platform via specialised miniapps for that purpose, and all new/change work will involve building/porting features as native miniapps.

At the appropriate point in time, the remainder of the miniapps are targeted for a final conversion effort, and the legacy platform is decommissioned.

What about Mobile?

Responsive design is a given, but if you want to integrate a micro-frontend into a Native Mobile app, it can be a challenge. Do you use a WebView? Do you try to transpile your miniapp using a hybrid framework? Or is it easier to just start from scratch?

For NAB-X Native we are taking a two-pronged approach.

1. For low volume miniapps that we want to reuse on mobile, we use a webview to surface the responsive web miniapp. To make this work, we provide a webview shell as part of the miniapp generator. There are corresponding webview miniapp capabilities built into the native apps.

2. For more important features, we are implementing a ReactNative UI capability as part of the generator, alongside a ReactNative Shell implementation baked into the Native app. This means that we can share non-ui miniapp code, the BFF, and provide a mobile targeted user experience as part of the same miniapp codebase.

Miniapp Monorepo

Federated Delivery Model

The model used for delivery of miniapps to customers and bankers rapidly is to allow the teams that own a given domain and its roadmap to also build the related re-usable miniapps.

A domain team can build and deploy a miniapp into their own nab-x based hosting environment without involvement from platform teams.

Once a miniapp has passed all the standard compliance and integration tests, it can be activated in multiple platforms. This may either be via code or config depending on the platform shell. The nab-x team are working on a future state shell that will standardise this and optimise for delivery of tailored miniapps.

Tailoring of user experience

As we know the actions that a given user can perform at an API level, it makes sense to also customise the user experience to reflect this. We use the NAB-X Tailoring Engine to achieve this, by connecting to the same policy store that drives microservice entitlements checks, and mapping these to user capabilities.

In addition to this, we plan to allow users to set preferences that will control which miniapps they see, and as an extension move towards ML based tailoring that will adapt to user behaviour.

What’s next?

We believe that we have a model that will allow third party developers and platforms to build capabilities that can be integrated into our shells to provide customers with features they will love, and we want your help.

There are two paths to contribution:

1. Join NAB to help build the NAB-X platform.

2. Work with us as a 3rd party to build miniapps for us to integrate.

The second path still requires a bit of work on our part. We are aiming to opensource the following tools to help you build and test miniapps.

1. nab-x miniapp generator: creates the scaffolding for new miniapps.

2. nab-x sdk: the toolchain used to perform common actions and integrate with shells.

3. the nab GEL React component library: for consistent user experience.

4. build a dedicated hosting environment for 3rd party miniapps.

5. guides and documentation.

If you’re interested in working in technology at NAB, you can find out more here.

About the author: Andrew Vaughan is a Senior Manager Distinguished Engineer/Arch at NAB. Prior to this, he’s held senior developer roles at CBA, AMP and MLC.

--

--

National Australia Bank

NAB’s official account for all things tech and digital. Inspiring readers to rethink bank tech, its use of data and creating seamless digital experiences.