DEV Community

Cover image for Building a Modular Decoupled Backend using a Monorepo
Sibelius Seraphini for Woovi

Posted on

Building a Modular Decoupled Backend using a Monorepo

There are a lot of articles about why you should decouple your backend to move faster, but very few content on how to practically do it.
This article is a practical approach that we use at Woovi to decouple our backend endpoints breaking them into packages in a monorepo.
As we scale we can easily convert them to their own microservices.

Creating a decoupled backend

Decoupled

We should first start designing what endpoint patterns we are going to expose.
In the image above we have five patterns: /login, /register, /home, /api, and /provider.
You can think about each of these patterns as separate services, but we will deploy them in a single service to simplify deployment and maintenance.

For each endpoint pattern, we are going to create a package in our monorepo, and each package will have its own Koa Router.

The monorepo for these 5 "services" will be like this:



packages
- login
- register
- home
- api
- provider


Enter fullscreen mode Exit fullscreen mode

A sample koa router code is described below:



import Router from '@koa/router';

export const getApiRouter = () => {
  const apiRouter = new Router();

  apiRouter.all('/api/status', statusMiddleware);
  apiRouter.get('/api/v1/charge', chargeGet);
  apiRouter.post('/api/v1/charge', chargePost);
  apiRouter.get('/api/v1/transaction', transactionGet);
  apiRouter.post('/api/v1/transaction', transactionPost);

  return apiRouter;
}


Enter fullscreen mode Exit fullscreen mode

Only using a Koa router is not enough to expose these endpoints.
We need a Koa app to make this possible.

We will create a new package to combine all these "services" endpoints and expose them.



packages
...
- woovi-server


Enter fullscreen mode Exit fullscreen mode

It will need an app.ts file that has the Koa app with some middleware and will combine all these "services" endpoints:



const app = new Koa({
  proxy: true, // we are behind a proxy
  keys: [config.JWT_KEY],
});

//Add your middleware here
app.use()

// combine all routes here
const apiRouter = getApiRouter();
const homeRouter = getHomeRouter();

app.use(apiRouter.routes()).use(apiRouter.allowedMethods());
app.use(homeRouter.routes()).use(homeRouter.allowedMethods());


Enter fullscreen mode Exit fullscreen mode

Then you can run the server



(async () => {
  const server = createServer(app.callback());

  server.listen(config.SERVER_PORT)
})();


Enter fullscreen mode Exit fullscreen mode

This way each "service"/package keeps its code separate, following the domain-driven design.

Breaking in microservices

As you scale, you can decide to move to microservices.
Instead of using a single server to serve all your endpoints, you can have many servers.
If you follow the approach above, it is as simple as creating a new Koa app for each package that you want to decouple in a new service.

In Conclusion

This approach lets you decouple your backend, making it clear the boundary of each separate "service" without all the burden of a full microservices approach. You get the benefits without the drawbacks.

You can read more about DDD here Domain Driven Design using a Monorepo


Woovi
Woovi is a Startup that enables shoppers to pay as they like. Woovi provides instant payment solutions for merchants to accept orders to make this possible.

If you want to work with us, we are hiring!

Top comments (3)

Collapse
 
zerbinidamata profile image
Rafael Zerbini

When you break to microservices there a lot of questions you need to answer generally:

  • Every package will have a different docker image or the same? Same for dependencies
  • How do you deal with shared components between packages?

And so on, would be nice to have a text about this

Collapse
 
brunomguimaraes profile image
Bruno Guimarães

Hi, cool post

Could share a little bit about the decision on using Koa? Since Woovi is a payment solution product I wonder if that's something to do with that.

Collapse
 
sibelius profile image
Sibelius Seraphini

Koa is the evolution of express, it would be the same with express