In this brief article I want to share some comments on the Twelve-Factor App.
The Twelve-Factor App is a kind of manifesto for building web applications that was written in 2015 by the creators of the Heroku platform.
If you don’t know about it read it! if you already know, you can maybe read it again 😉
It’s a really good compilation of best practices.
However in my opinion not every factor is of equal importance. And most companies nowadays are somewhere in the transition to cloud infrastructures.
Hence I want to share some thoughts on the individual factors in the light of building cloud-native microservices.
Subversion and Mercurial are mentioned there alongside Git.
But seriously: Use Git! Other programmers will laugh at you and not take you serious if you don’t!
If you don’t do this your speed will slow down and you’ll often see confused faces when the size and number of your microservices grow.
But there is no need to be super-strict with that rule and declare each and every dependency. For example if your infrastructure sets up each machine with a set of pre-installed software, your applications can just assume that it’s there without explicitly declaring it in my opinion.
However in that case make sure to fail fast if it isn’t there!
Make sure you have your configuration stored in a separate place from the code!
A thing to look at is the Spring Cloud Config project here.
Your code shouldn’t know a difference whether your database or message broker runs locally or in the cloud.
Just an update in the configuration is necessary to change that. Aim for maximum flexibility!
A project that aims to simplify this is Spring Cloud Connectors.
It’s nice to have a setup like described on the page, but it is time consuming to set it up.
Depending on your approach you’ll probably have to live with an incomplete pipeline here and it may involve some manual steps.
The key word is “stateless” here. You should not rely on any state in memory, on the file system or having sticky sessions in a web application (where the session does not come from the server/servlet container).
An application without state is easier to manage, has better scaling abilities and should usually be more robust.
Most cool frameworks nowadays give you that for free with an embedded servlet container (I’m looking at you Spring Boot). But from my point of view it is negotiable whether this is necessary or not.
If you have some deployment templates in place you can easily deploy a servlet container and throw your *.war file in there, just as easy as starting your all-in-one *.jar.
Of course this depends on your setup. Most PaaS providers would expect port binding of services.
This is all about keeping the small parts of an application working independently and running them as separate processes for the goal of having better scaling abilities. I wouldn’t worry too much about this factor until scaling becomes an issue.
This depends largely on your needs, how often you plan to release and deploy new code and your scaling requirements.
That said having robustness against crashing is always important. To help that in a microservice architecture good things to use are robust backing messaging queues (like RabbitMQ), containers (in a way that you can easily swap running instances with each other without having to worry about startup times) and – on a lower level – the application of the circuit breaker pattern.
This lowers the risk of something unexpected happening in production and is hence a good advice. Depending on the circumstances it can be quite hard to achieve.
You may get away with not having this, but you should still aim for the closest similarity. For example one thing that may be omitted is when you have a database cluster in production but a single instance in the development setup.
A point where I partly disagree with the recommendation from the twelve factor app manifest: Logging everything to stdout and have a third-party software deal with that.
Having logging frameworks like slf4j you can manage your logging inside your application without having to rely on third-party software for that. However you should still send your logs to a centralized logging facility, leveraging something like the well-known ELK-Stack for having them archived and being able to do data-mining on it.
The examples used on the twelve-factor app page are a bit unusual for a Java microservice developer as it mentions ruby and python scripts.
But the same stuff exists in the Java world. Instead of rake migrations in ruby you would have Flyway database migrations.
For doing micro-admin tasks (like changing the log level) you can have things like Spring Boot Admin…
I hope you agree mostly with my comments on the twelve-factor app and maybe found something useful out of my recommendations/comments.
In my opinion twelve-factor app is a great set of advice and I can only recommend adopting as much as possible if your aim is to go cloud native.
However I emphasize that not all factors may be of equal importance to your situation and that’s why I added an importance rating on the individual factors.
Your mileage may vary. This article is only my individual point of view.
Feel free to discuss!