Who in tech doesn’t want to move faster?
Dan Langevin is no exception. As founder and CTO of Vericred, he leads a team of engineers operating in the busy intersection of data services and healthcare. It’s a rapidly changing field and Vericred’s software has to be able to adapt on a dime to keep up. That’s why he turned to microservices architecture.
Instead of a single sprawling monolith, microservices architecture is comprised of a series of tools that break functions down into smaller chunks. That means engineers can make quick iterations on one function without it affecting the entire platform. According to Langevin, that means tech stays lightweight and scalable with shorter production cycles.
Sound dreamy? Langevin is careful to note that when used incorrectly, microservices can overcomplicate a system. If microservices don’t operate independently of each other, they wind up creating a complicated monolith of their own that’s difficult to manage.
So how can teams best utilize microservices to simplify their tech? Langevin walked Built In NYC through his best practices for keeping microservice architecture as it should be: small.
How did you decide a microservices architecture was right for your business?
We determined that extricating our higher volume services and endpoints from our purpose-specific monoliths would increase scalability and flexibility of deployment by removing unnecessary entanglements that typically occur within monoliths.
We spent some time investigating available tooling before deciding on Lambda and API Gateway for services that have an external interface. We chose Step Functions, Lambda and SQS for services that run batch processes or event-based processes that don’t require a real-time response. Finally, we selected a handful of candidates to move into this architecture and build them out as proof of concepts.
What are the pros and cons you've experienced from implementing a microservices architecture?
We can distill our philosophy on microservices down to this: A microservice must provide a clear API and store its data independently of any other service. This means that two microservices should not rely on the same shared resource, like a database. If two microservices rely on the same shared data store, they are no longer a microservice but instead a more difficult-to-maintain version of a monolith.
By chaining services that each isolate data and provide an API, we can ensure that our microservices are, in fact, ‘micro.’”
A microservice should have a clear API specifying its inputs and outputs and it must own that contract definition. The systems that produce the inputs to that API should be tested such that that contract is fulfilled.
For example, we may have a microservice that processes a large file. The format of that file is the contract to the service’s API. Whatever system produces that file should be tested so that it fulfills our microservice’s API. Let’s say that our microservice processes that large file and sends API requests to ingest data from that file. It now becomes the producer of data that is consumed by a different microservice and no longer owns the contract — but must instead conform to the contract of the service that consumes its API requests. It should have unit tests to that effect.
By chaining services that each isolate data and provide an API, we can ensure that our microservices are, in fact, “micro.”
Tell us a bit about your team's microservices architecture.
Our team uses Ruby and Rust. We use Postgres, Elasticsearch, Redis and Athena/S3 as data stores, deployed on AWS and Heroku. The microservice architecture we employ is primarily Lambda, though we do have some smaller apps hosted on Heroku that could potentially be considered microservices.
This architecture works for us because it combines scalability and isolation of microservices for specific purposes with the ease of development and deployment that comes from purpose-specific monoliths.