Skip navigation
All Places > Developer News and Updates > Blog > 2020 > May
2020

The term microservices is used fairly frequently when people talk about developing modern software solutions, but what does that actually mean for payment and financial applications? Let's take a broad look at what a microservices architecture is, how to develop applications using this architectural style, and the benefits of developing applications this way.

 

What are microservices?

When we talk about microservices in application development, we are talking about applications built as a suite of small services. Each service generally contains its own business function, run in its own context, with its own resources.

Microservices typically have the ability to communicate with other services in a loosely coupled way, often over RESTful APIs. This allows developers to implement each service as its own self-contained action, which provides a lot of flexibility and reuse of developed components.

There are a number of principles that are generally adopted when developing microservices for application design and development. Many of these principles are adopted to ensure that systems are robust, supportable, and can be developed quickly.

Let's take a look at these architectural principles.

Organized by business functions

The first key principle of microservices is the organization by business function. This principle allows you to slice up the work into potential services that can be composed together to form a business process. For example, a typical banking application might be broken into some of the following microservices:

  • Check balance
  • Make payment
  • Transfer funds
  • View transactions
  • Authenticate user

 

One of the important design considerations when using this principle is to ensure that the business function is as generic as possible. For instance, the service "check balance" could be defined as "check savings account balance." However, if you think of this as a service, this would be too limiting and really the only difference between the two would be the account type that can be passed in as a parameter.

Highly maintainable and testable

The next principle is ensuring that the services are maintainable and testable. This principle can be a little hard to understand, but it is primarily based on the concept of your services being relatively small.

Each service should contain a minimal number of steps while still remaining as generic as possible. This allows your service to be easily understandable, making it a lot easier to maintain. It also simplifies the testing required for the service and, coupled with a test-driven development process, also ensures that the service components can be easily tested.

Loosely coupled

Trying to develop services free of dependencies is the most challenging aspect of a microservices architecture. There are a number of ways to achieve loose coupling, and the use of a messaging system that implements a publish/subscribe mechanism provides a good way to achieve this.

Independently deployable

Allowing services to be independently deployable results in a lot of flexibility when deploying new service components, updating existing components, and isolating components.

Owned by a small team

Finally, each service can also be owned by small teams. Rather than multiple large teams owning large applications, finding the team that supports specific functionality is a lot easier with applications composed of small services.

Benefits of adopting a microservices architecture

Developing software using a microservices architecture practice changes the way historic development practices work. This style of development offers a lot of practical benefits when adopted.

Modularity enables a lot of benefits for large scale applications, particularly in finance. Being able to add, remove, or recompose lines of business and business processes by adding, moving, or removing modular services enables a lot of flexibility and responsiveness.

Having a suite of individually scalable services also allows applications to flex with burst workloads in a cost-effective manner. For instance, if bulk payments are generated or large numbers of users are sending funds, those specific services can scale independently to meet the load, rather than the whole application.

Microservices, by design, have a great affinity with cloud offerings, allowing services to deployed onto a cloud infrastructure using three different models:

  • Infrastructure as a Service: You manage services from the operating system up.
  • Platform as a Service: You manage services from the container up.
  • Serverless: You manage only your services.

 

Your build and deployment pipelines for services can be vastly improved and automated. Services should minimize changes to their interfaces, allowing changes and updates to occur with almost none of the downtime associated with traditional build and deployment activities.

Microservices support easier troubleshooting. This benefit requires good practices, but essentially it is a lot easier to see when components of your application are misbehaving. Because services are testable and visible, you can see when a service is failing its tests, using too many resources, or generating error logs.

 

Finally, managing the building of large, complex applications becomes a lot easier. As you go through the sections of your system, you will be defining small, manageable services that allow you to build, test, and deploy portions of your application quickly. As application development continues, much of the work becomes less about developing new services and more about adapting and composing services in different ways.

Deployment options

As mentioned, there are several ways to deploy cloud-based applications that also extend to on-premises and hybrid scenarios.

Traditionally, applications were deployed as a few big components on bare metal servers. You can still do this with microservices, and it may be particularly useful for services used in batch processes. However, most applications built using microservices try to take advantage of being able to scale automatically as required.

Hosting applications in virtual environments is fairly common practice with on-premises deployments. Virtual environments allow a microservices application to scale in some ways, but they’re still not as flexible as other environments. For instance, services used as part of a batch process that can start and scale virtual machines to crunch large amounts of transactions work reasonably well when deployed using virtual environments.

Cloud environments offer a large amount of flexibility when deploying microservices applications, with a number of options around how much of the environment to manage and almost limitless resources to scale individual services. Microservices do really well when deployed to cloud environments.

Running services within containers provide the most flexibility and control, albeit with additional overhead for maintaining and monitoring containers. Containers like Docker provide a self-contained environment for services to run in. Orchestration services like Kubernetes and Docker Swarm allow you to run and scale containerized services across both on-premises and cloud infrastructures, allowing for a truly hybrid deployment model.

Writing microservices

Microservices themselves can be developed with almost any language and framework. This includes Java, C#, JavaScript, Python, C++, Rust, Golang, and more. Part of this freedom allows you to migrate to a microservices architecture with the language your developers currently know and use. It also allows you to transition applications into other languages without the need to rewrite the whole application.

For instance, a payment processing service that runs primarily through a batch process might be written in Rust to ensure it runs as optimally as possible.

The other consideration of applications built using a microservices architecture is whether to adopt a truly serverless build leveraging Lambda (AWS) or Functions (Azure). These services allow you to build and deploy services without the need to configure scaling, servers, containers, or other components.

Next steps

You had a broad look at microservices, their benefits, and how to approach designing and developing applications using this architecture. While they shouldn't be used for every application, a microservices pattern can add a lot of flexibility for large applications and can really leverage the benefits of cloud services.

 

If you are looking to adopt this pattern or build your financial application in the cloud, check out the in-depth microservices guidance from AWS (https://aws.amazon.com/microservices/) or Azure (https://docs.microsoft.com/en-us/azure/architecture/microservices/).

 

If you have questions, be sure, and post your question in our community forum. 

Principles matter. For any group, of any size, principles bring clarity, they provide a sense of purpose and they offer direction when the road ahead is difficult or complex. This is certainly true at Access Worldpay team, where test-driven development (TDD) is a guiding principle. Does it still hold true when put under stress?

 

At Access Worldpay, everything is tested, all the time, and the phrase “If it’s not tested, it’s broken” has become a mantra for the team. Rigorously applying this principle takes effort, even in software development where TDD has become commonplace. Maintaining the same rigour becomes far more challenging in newer areas, particularly infrastructure code. Why?

 

Big change, new skills

Infrastructure itself has changed rapidly and significantly, from localized hardware and software to remotely-located cloud-hosted services, such as AWS. This requires users to configure and code remote servers to their precise needs and then test that this code meets their required specifications.

Testing infrastructure code is, therefore, an entirely new discipline – one that is wholly embraced by Access Worldpay, albeit with open eyes. Dominic Byrne, a cloud engineer, explains: “Infrastructure code at the moment is in its infancy – for example, terraforming is releasing at a pretty rapid rate. It’s what we use, but it’s still in beta.”

 

New code, no context

As a result, Dominic explains, reliable testing frameworks do not yet exist. “People are reluctant to develop them because early ones don’t work anymore,” he says. “They were just built around a basic configuration plan so they become completely useless whenever the structure of that plan changes.”

 

What’s more, many cloud engineers are unused to TDD. “In the past, infrastructure engineers and application developers were two different teams,” says Daniel Beddoe, a senior software engineer at Access Worldpay. In addition, he explains, people used to question why infrastructure configuration files needed testing at all. “It turns out there’s every need to do so because now you could write something very bad in just one line of configuration that could mess up your whole infrastructure.”

 

Same team, single path

Instead of treating application and infrastructure engineering separately, Access Worldpay takes the same approach to every piece of work. “We’re making everything one team and applying practices from application development into infrastructure,” says Dan. This means identifying requirements and defining success before work begins on each project, whatever its nature: “We’re saying that you need to write tests for your infrastructure just as much as you need them for your applications.”

 

Part of this shift is organic. “People are increasingly moving from application development into operations and infrastructure,” Dominic explains. “They like the tools they currently use and they want to bring the same principles into infrastructure code.”


Live tests, late feedback

That’s easier said than done, because infrastructure code is tested against a live service, which makes the feedback loop much longer. “Without building anything, loading my spec files and running my tests on my current project averages about 44 seconds,” says Dominic: “For an application developer, tests taking that long to finish aren’t good.”

 

A central goal, therefore, is to ensure that this feedback cycle remains manageable – particularly since it lengthens further whenever code is altered. “If I change, say, an elastic search server, the loop goes from 44 seconds to 10 minutes at least – that’s just the reality of those services online,” Dominic explains. “So for infrastructure code, following basic TDD principles where you write your tests and watch them fail means allowing for the time it takes in your feedback loop.” That this can be difficult is hardly a surprise given the pioneering nature of the work, but the team has devised new ways to ameliorate these challenges.


Testing spec, teaming up

One approach is to change how infrastructure code is written before testing begins. Instead of writing and testing segments of code incrementally and enduring the long feedback loop each time, “you try to write each instance as the final product,” Dominic explains. “For example, saying ‘I want it to have these forwarding rules; I want this origin to match this specification,’ and you write all that and then you start your feedback loop to test that spec.”

 

The issue with working this way, of course, is unpicking the code should a test fail. But perhaps such workarounds need only be temporary; as infrastructure code is more widely adopted and tested, eventually more robust frameworks to support those tests may be built

 

In the meantime, Access Worldpay is supporting TDD for infrastructure code by physically pairing software developers and cloud engineers to shed old, silo thinking, and encourage the broader outlook that cloud-based infrastructure requires. “There’s a whole world of delivery to actually get your thing to work – you need to know how to get your application out into the world,” Dominic says: “Just knowing how it works locally isn’t useful for anyone.”

 

Towards better, even slowly

However imperfect today’s situation, Access Worldpay remains committed to testing infrastructure code. Partly this is to uphold the principle that TDD produces better, more reliable products for its customers, and partly because testing documents systems more clearly. This makes it easier for product owners to prioritize future work and for new team-mates to make useful changes quickly and with confidence.

 

The end goal of being able to apply traditional application development practices to infrastructure code in a consistent, rigorous way is still some way off. In the meantime, Access Worldpay is trying to develop a methodology that makes infrastructure code tests not only rigorous but also practical – staying true to its core principle while always analyzing its approach and making further refinements wherever necessary or possible. Progress, however uncertain, is still progress.