PlantUML Pleasantness: Setting Arrow Directions

PlantUML mostly does a good job organizing elements and arrows in the resulting diagram. But we can help PlantUML by defining the arrow direction in our PlantUML definition. We can use the keywords up, down, left and right inside the arrow definition.

In the following example we have five rectangles connected with arrows. We define the arrow direction for each arrow.

We can even only use the first letters of the direction. The following definition will render the same diagram:

The resulting diagram looks like this:

Written with PlantUML 1.2018.6.

Original post

Microservice architecture diagram composition

A low code approach to composing microservice architecture diagrams from per service context diagrams.


On a recent assignment I was one of multiple new engineers joining a start-up transitioning into a scale-up. The past two years had been spent rapidly developing to prove the concept, and while at the outset some diagrams were drawn up, at the time I joined these were outdated, lacking or even misleading. To help get ourselves and other new developers up to speed, Andrew Morgan and I set out to create architecture diagrams for the system as a whole.


In typical fashion these days, the system consists of microservices communicating with one-another in a mix of direct HTTP invocation and by publishing and subscribing to Kafka topics. In the absence of tracing information or tools to deduce the diagrams, we settled on a simple approach:

  1. Create context diagrams per service
    Using PlantUML we created diagrams for each service, in the root of the project repository. The diagrams contain the topics published/subscribed to, and direct HTTP invocations going out from the service, as well as any data stores and interactions with external services.
  2. Compose overall diagrams
    Using the GitLab API we gather all projects with a particular tag, and for those projects extract the PlantUML diagrams from the repository. These are then combined into a single overall diagram by stripping out the @start/enduml tags and simply appending them one after the other. By using distinct tags we’re able to create diagrams for services in active development, in production or zoom in on a particular aspect such as data processing. New projects are automatically picked up, and warnings are sent out when diagrams are missing.
  3. Expose diagrams as images
    A nightly pipeline creates images for each service individually, as well as a number of composite diagram images. The individual service diagrams are visualized in the GitLab repository README of each project, giving passing developers a quick glance of the context of a single service. The composed service diagrams are visualized in the README of the composition project, for easy reference elsewhere.

Compose individual diagrams


The code consists of a Gradle task, a Gradle build file and a GitLab CI file. We place the task in the buildSrc directory, so we can easily use it in our project’s build.gradle file.

Gradle Task

buildSrc build.gradle

Project build.gradle



We chose this approach as a simple way to document the overall architecture, in a landscape that’s still undergoing changes and needs to be kept up to date. Having the individual diagrams close to the code ensures the individual diagrams are easily maintained, while the overall diagrams always reflect the latest changes. These qualities are not as easily achieved when the diagram is further removed from the code. The low-tech approach allows anyone to quickly contribute diagrams, with minimal tooling.


As the overall diagrams are composed from individual diagrams, a common set of guidelines should be enforced for a consistent overall view. Inconsistent use of arrow directionality for instance, can have big consequences for the overall diagram layout. Also, layout of the overall diagram is not stable with regards to previous versions in light of recent changes. Introduction of a new inter-service-dependency for example, can rearrange large parts of the diagram, which can confuse those familiar with previous versions.

Future extensions

GitLab PlantUML integration

Above we use separate files for the diagrams for simplicity, and render the diagrams using the PlantUML jar. However, GitLab can integrate with PlantUML directly to visualize diagrams present in any AsciiDoc and Markdown documents in a repository. This would allow one to make the diagrams part of the README for instance, with only slight changes to the diagram composition.

Other platforms

While the code above uses the GitLab API the same approach can just as easily be applied to different platforms such as GitHub.

Alternative diagrams

As briefly mentioned above, there are alternatives to generate overall system architecture diagrams. One such approach is Structurizer, which inspects the code to generate diagrams at multiple levels. Another, more deductive approach is to use the operational platform and available tracing information to compose diagrams based on runtime service dependencies. These and more are explored to extend and supplement the current approach.

Starting as a new technical lead – Introducing change

Congratulations! Someone has made the wise decision to hire you as the new technical lead. It is an exciting time. You start in a new environment, will be working with a new team and maybe even have to learn new technologies along the way. This can be quite challenging. In this two-part article I want to share my personal views regarding Introducing change and shaping teams as a technical lead.

Introducing change

When starting in this new environment you probably bring lots of energy and want to leverage your experience to change things for the better. In my opinion introducing changes in a new environment requires some consideration.


As technical lead you are (hopefully) up to date with the latest principles and technology trends. As technical lead your life purpose is to “build the thing right” because “building the right thing” is someone else’s concern ;-) You quickly determine that the project you inherited has some some design/architectural issues that should be addressed promptly. So the next day you climb on a chair and give a passionate speech about how things need to change. Wait right there! Even if you are right, you need to consider some things.

First remember that you are judging the work of the current development team. They probably put their heart and soul into it. Secondly there are often influences from outside the team that drive technical decisions. The most obvious are deadline but there are others. Don’t be judgemental about the current state of development, because it  can quickly create a gap between you and the rest of the team.

Change velocity

Changing something requires some time for the team to adjust. This means you can’t pile change on change, even if they are beneficial. If you make to many changes you effectively try to change the team’s entire way of working.

Consider the change velocity of the team. This doesn’t have anything to do with experience. Sometimes junior team members find it easy to adopt new ways of working while the seniors are reluctant to change their ways. Getting this right requires at least experience and some feeling.

Quick wins

So am I telling you that you can’t propose any changes at all? Not really. After all you were hired as lead so you get some credits from the get go. You can introduce some minor changes to the product or processes. Often some minor changes can help the team work more efficiently. Maybe eliminate some small repetitive tasks for example. Proposing some good changes can really help establish your position as lead. Also people are more receptive to minor changes then they are to big changes. Just be aware of how many of these changes the team can adopt.

Bigger changes

Before you start introducing big changes, I think it is important to take some time to reflect on past and present. During this time quickly gather information. Try and get to know about:

  1. the team;
  2. the system’s architecture;
  3. the technologies used;
  4. the history and past architectural/design decisions;
  5. The external systems your system interfaces with;
  6. the project stakeholders (business, privacy, security…)

Don’t be afraid to ask questions. A lot of information will be in the minds of the team members you work with. This information will help you prioritize and drive your future decisions. When you have settled in the team and have a good sense of the context you are operating in, you can start discussing the changes that are most urgent.


When introducing change  try to not be that bull in the china shop. Instead take some time to really get to know the history of a project, the team members who work on it and the context that you operate in. If you are able to identify some quick wins you can propose some of them to the team. Use the information that you gathered to prioritize and drive any major changes that you deem necessary and propose them at an appropriate moment. Consider the velocity at which your team can adopt these changes to prevent piling on to many changes at the same time.

Awesome Asciidoctor: Use Diagram Block Macro To Include Diagrams

With the Asciidoctor diagram extension we can include diagrams that are written in plain text. For example PlantUML or Ditaa diagrams. The extension offers a block processor where we include the diagram definitions in our Asciidoctor document. But there is also a block macro processor. With the block macro processor we can refer to an external file. The file is processed and the resulting image is in our output document.

Continue reading

PlantUML Pleasantness: Creating Our Own Sprites

PlantUML supports sprites to be used in diagrams. A sprite is text encoded monochrome graphic we can reference using the syntax <$spriteName>. The sprite is defined using hexadecimal values. We can define a set of hexadecimal values to create our sprite, but we can also generate the correct values from for example a PNG image.

Continue reading

PlantUML Pleasantness: Layout Elements With Hidden Lines

In a previous post we learned how to use a together block to keep elements together. We can also layout elements in a different way: using hidden lines. We define our elements and by using the keyword [hidden] in our line definition the elements are layout as if there was a line, but we don’t see it. This gives us great flexibility on how we layout our elements.

Continue reading

Awesome Asciidoctor: Use Only Block As List Item

When we define a list in Asciidoctor we usually have a list item that is a paragraph. But if we want to have a block as list item we need to add an extra {blank} element to make sure the block is parsed correctly as list item. Because a list item starts with a . or a * at the beginning of a line and a block also is defined on the beginning of the line, we must add the extra {blank} element. Together with the list item continuation (+) we can have a list with blocks.

Continue reading

PlantUML Pleasantness: Align Multi-line Label Text

PlantUML has some features that come from the underlying software to create diagrams. Graphviz is used by PlantUML and we can use Graphviz features in our PlantUML diagrams. For example we can align multi-line text of labels to be either center (default), left or right aligned using a Graphviz feature. When we want to text to be center aligned we simply use the new-line character \n. If we want to have our text left aligned we use \l instead of \n. And to right align the text we use \r.

Continue reading

Awesome Asciidoctor: Prevent Transformation of URL to Hyperlink

Normally if we type an URL in Asciidoctor that starts with a scheme Asciidoctor knows about, the URL is turned into a hyperlink. The following schemes are recognized by Asciidoctor:

  • http
  • https
  • ftp
  • irc
  • mailto

If we want to keep our URL as text and not a link we must prepend our URL with a backslash (\). This way Asciidoctor will not transform the URL to a hyperlink in our output.

In the following example we have URL that is transformed to a link, followed by the same URL but with a backslash (\) before it, that is not transformed:

If we transform our document to HTML with Asciidoctor we get the following result:

Written with Asciidoctor

Original post