Portal

2018 - now

Jumping on the microservices craze (which allows me to experiment with all kinds of technologies), I've built a personal portal. It's helping me simplify my life. Or at least, that's the purpose :)

  • Portal

Why microservices?

I expect that the functionality of the portal will change often. It adapts to my life.

That why I have chosen to design the portal as microservices. The goal is to easily write new functionality and disable unused modules. This decision allows me to use different technologies, making it interesting to toy around with new technology hypes.

Functionalities include:

  • a todo app, optimized for my personal needs
  • an activity suggestion app, which takes into account several elements (like the weather)
  • a "housagotchi", which is actually a reminder app to do tasks in the households. I'd rather make "the house" angry, than my wife ;)
  • similar reminder apps for fitness an social activities

High level Architecture

High-level-architecure

The back-end

Communication between modules

Since modules should be easily removed/replaced/introduced, it's important for modules to have as less dependencies on each other as possible. On the other hand, I expect the portal to be a smart, proactive system, which requires modules to be sharing data all the time.

The preferred communication method is asynchronous, generic data exchange. When something occurs that could be of interesting for other modules, the module is expected to publicize this information on the Event topic. Every other module that's interested will receive this information, doing something meaningful, or throwing the message away.

In case that synchronous communication is required, for example for queries of other modules so that information can be shown in the front-end, REST webservices should be used.

The front-end

There is a dedicated front-end module which contains the front-end components for every backend module.

Wait, in the spirit of the back-end, shouldn't this monolithic front-end also be split into microservices?

The first attempt: a true modular front-end

While the back-end functionality can be kept apart in separate components (if some supporting components are put in place), this is much harder in the front-end. At first, I've tried to create a "real modular" front-end.

  • Every back-end module has its own front-end module (when needed).
  • The front-end and back-end module are kept in the same Git repository, living nicely together.
  • A front-end core component loads all these separate modules in one page.

Still, the user will access the app in one place only. This means I have to assemble all components in one app, the so called "core app". This core app

  • is the access point
  • contains a menu to go from one app to the other
  • and displays the chosen module.

These are the options that I thought of, to realize this:

  • Option 1: use web components to load everything in the same domain.
    • The Angular/React/Polymer/... needs to be loaded for every component, again and again
    • Static resources, like images, css, ... cannot be referenced relatively.
    • The manifest file still needs to be shared in a front-end-core component, which means it's still no completely autonomous commponent.
  • Option 2: use i-frames to keep everything in separate contexts
    • The Angular/React/Polymer/... needs to be loaded for every component, again and again
    • I'll run into the safety limitations of cross-domain-origins pretty fast. For example: I cannot transfer a JWT token from one domain to another, unless I start using a proxy. In that case, I run into the same issues I have without option 1.
    • Frames look horrible on mobile. It will also be noticeable that the parent frame loads first, the i-frame next.

Neither options cut it. I want a highly-functioning progressive web app.

Current attempt: a single front-end, that consists of modules/web components with shared static resources

Ok, my conclusion is that a high-performing front-end cannot be split into completely separate modules, due to the design of the web.

The best second thing is to have a single front-end, but keep the different domains separated via modules or web components.

The unsplittable common part is kept in a single location. Efforts are made to keep these as small and clear as possible.

The front-end's architecture

  • The core framework is written in Angular.
    • At the moment of writing, this framework offers the best options regarding building a progressive web app.
    • Angular is also perfectly capable to load web components, which frees up my choice in front-end technologies.
  • I can choose to write each module
    • in Angular
    • in another technology, as long as I can pack it in a web component
  • All static resources, like the manifest, css, images, ... are kept in one place.

7 years later: lessons learned

I'm still happily using all the features I've built. Maintaining them... that doesn't really happen too much.

In the past 7 years, since I started this project, my life has changed. The largest bulk of my time goes to my familiy - and especially my son.

An underestimated maintenance burden

That's also the biggest problem of this project: while it was super nice to build 15+ smaller modules, all in a technology that fits the use case best, maintaining all these different things became a burden.

Minimizing the maintenance burden, without losing the benifits of nicely split codebases

If I ever get the freedom to do a rewrite, I'd probably go for a nice Spring Boot-based backend, modularized with Spring Boot Modulith.

This way, I can keep the components separately, while

  • maintaining only one stack
  • simplifying communication between modules (in-memory or database-stored events, vs JMS)
  • simplfying cross-cutting concerns, like security.
Me and my son

Stijn Hooft

Software engineer, specialized in Java and web technologies

Mail LinkedIn Github