Having a tech stack that works for your company and its needs is really important; but what should that look like? Dylan Harbour, the Group Engineering CTO at Ringier One Africa Media (ROAM), spoke to us about when setting up shared services makes sense for a company, and what he’s learned about the impact it has on his tech teams.
ROAM focuses on bringing marketplaces to the African continent. With offices in Nigeria, Ghana, Tanzania, Kenya, Senegal, and a number of other African countries, a lot of Dylan’s work happens across distributed teams. As a result, he’s thought a lot about how his development teams operate cross-functionally.
Before Dylan started setting up shared services, his teams ran production applications through a Laravel application, with a central classified core package and a lot of shared code: “We were able to get quite good economies of scale out of our development teams,” Dylan says, “in doing the implementation of features once, and rolling it out across multiple different businesses, all by having a shared code base.”
However, the industry has matured since then, and Dylan explains that it’s more often the case that shared code bases are quite ‘brittle’ - in other words, shared code between multiple dev teams or business units is hard to scale or test independently because of how much tech has changed.
But Dylan is solving this problem with shared services. Here’s the benefits Dylan has experienced with shared services, how he’s made it effective, and in what cases you actually need shared services.
The benefits of shared services
Dylan’s team is still in the process of setting up their shared services properly, but they’re already experiencing the benefits of having them:
Isolating complexities of a system into smaller pieces
This makes it easier to test, roll out, and upgrade a system, with less effort and risk to the business. “We don't want to take something that's got a very high cognitive load,” Dylan explains, “and put it on every single developer. We'd rather isolate that away, let them focus on just the things that are unique to their business case, and pull some complex features into a central place where they don't necessarily have to understand the ins-and-outs of how it works, if it's working, or when it's working.”
Centralising code base changes
This helps reduce the mindshare for each individual team, because they don’t have to update their own codebases every time something changes. In Dylan’s experience, this not only helps development move quicker in general, but also means “[teams] can assume that a ‘thing’ is being managed by somebody else, integrate with it happily, and not worry too much about having to get the details of that integration right.”
Building things once and rolling them out multiple times means it’s easier to support individual teams; they can also help each other. Dylan explains: “We work together as a big organisation rather than each team working independently, and not really knowing what the rest are doing.”
If you give different developers tasks to do, and they're not aligned with some type of central direction and controlled by some type of shared services, then you could end up with a lot of diversions in the approaches that are used. You could end up with duplication of code.
He gives an example of what this looks practically:
“If we look at, for example, switching a mail service provider to a new provider. That’s something that could be defined at group level, and we don't really want that to be the responsibility of each individual team to then go into their code base, _and _update it, and change it, and test it, and all the rest. We'd rather centralise as much as possible.”
Community standards make shared services more effective
Dylan says that his team has been able to make the process of setting up and operating on shared services really effective by working alongside a really robust set of community standards: “The challenges we faced with shared code were ones we managed to solve quite effectively with shared services that had community standards and frameworks at their core.”
One example of the way in which Dylan’s team used community standards is the Twelve-Factor app approach. They used this as a set of heuristics for working on development projects together, and helped them make decisions based on things they knew they agreed were ‘true’.
In short, the ‘12 rules’ of this approach are as follows:
- Codebase: One codebase tracked in revision control, many deploys
- Dependencies: Explicitly declare and isolate dependencies
- Config: Store config in the environment
- Backing services: Treat backing services as attached resources
- Build, release, run: Strictly separate build and run stages
- Processes: Execute the app as one or more stateless processes
- Port binding: Export services via port binding
- Concurrency: Scale-out via the process model
- Disposability: Maximise robustness with fast startup and graceful shutdown
- Dev/prod parity: Keep development, staging, and production as similar as possible
- Logs: Treat logs as event streams
- Admin processes: Run admin/management tasks as one-off processes
In their frontend, Dylan’s team has not only adopted VueJS (a client-side framework of a web application), but has also scaffolded their VueJS application, using Vue Enterprise Boilerplates. “It’s a more opinionated way of implementing VueJS,” he explains, “so that we have fewer conversations about what is right and wrong, and rather let the community standards and open-source approaches dictate that for us.”
Community standards have helped Dylan’s team reduce the number of conversations, documentation, and testing they have to do, which gives them more time and more mindshare to use elsewhere.
When you actually need shared services
If you’re unsure of whether to implement shared services or not, Dylan has found it becomes relatively easy to decide that by simply asking: "Does what I’m doing still make sense in this day and age?"
Some of the scenarios in which Dylan has found shared services help a team or business move forward more efficiently include:
- Running a monolith application in a business operating at scale
- Scaling a product or a business
- Isolating parts of your application really well
- Having multiple dev teams working on the same things
He’s found that the above situations are all vulnerable to the same challenges, all of which have become much easier to work around:
“In this day and age, if you can break down complexities, and isolate the way that you scale, you're going to be able to get better development effectiveness, be able to roll out features faster, and isolate those complexities away.”
Moreover, the huge change in tech infrastructure enables easier integration of microservices into one’s tech stack. Dylan says things like Lambdas and containerisation both support dev teams in breaking larger applications into smaller pieces, which helps teams work better, smarter, and inevitably faster as well.