3

I was reading the 12-factor app while thinking about the design of a personal project. I like a lot of what I read, but the following paragraph confused me:

In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.

I do not understand what it means for each env var to be "fully orthogonal" to the others. In colloquial usage, I generally think of orthogonality as "being able to change without regard to other items in the collection." However, some things that naturally break into multiple env variables (e.g. database host, port, username, and password) are also quite interdependent.

What does this statement mean?

apnorton
  • 359
  • 2
  • 10
  • In a nutshell, you should be able to change any config variable's value without having to check other values require a change in another value. – Edwin Buck Apr 07 '21 at 18:03

4 Answers4

4

The key to understanding what the author is saying is found in the previous paragraph:

Another aspect of config management is grouping. Sometimes apps batch config into named groups (often called “environments”) named after specific deploys, such as the development, test, and production environments in Rails...

So, for the part you are asking about,

In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy.

all the author is saying is that each environment variable can be changed independently of the others. So rather than just being limited to development, test, and production environments, you can have factorial(number of environment variables) environments.

It's an odd use of the word "orthogonal", as - outside of the maths of x,y charts and statistical independence - it's normally used to mean "unrelated", rather than "independent" as the author uses it here, but that's just semantics.

Of course, testers will tell you there's a flaw to using environment variables like this. That independence means there's also factorial(number of environment variables) environments to test for full test coverage. But often the flexibility and scalability will outweigh that disadvantage.

David Arno
  • 38,972
  • 9
  • 88
  • 121
1

‘Orthogonal’ means independent of each other. That implies that no information is duplicated or repeated in two variables, like a server name, and then a connection string that contains the server name.

In your example, database host, port, username, and password, would all be orthogonal, as they are not repeating anything, and are independently changeable (unless you repeat the port within the database host variable, which makes little sense)

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
Aganju
  • 1,453
  • 13
  • 15
0

Orthogonal means that environment variables are on different axes of the multidimensional configuration space. Changing the value of one has no effect on the values of others.

Imagine the concrete configuration of your system to be a point in a multidimensional space where each dimension is defined by the possible values of one variable. The variables are orthogonal if you can change its value and the point (= the system) is only moved on the axis of this variable. The point does not move on the axis of all other variables.

The steering of a helicopter is not orthogonal. The pilot always has to counter side effects of a change he makes to one steering element by also changing the other steering elements.

To make configuration orthogonal, for example changing the hostname of the database server must not force you to change the username and password, too. It must be possible to leave them unchanged without making the system unusable.

Kilian Foth
  • 107,706
  • 45
  • 295
  • 310
0

Orthogonal is a math term, borrowed for Computer Science. It only makes sense in talking about a value in relationship to other values.

An orthogonal value can change without the other variables changing. In math, this feature indicates it is independent of the other values. Sometimes people use this independence to indicate it is a measurement in a different "dimension" than the other items.

The 12 factor use of orthogonal is borrowing from these ideas, they clearly want something that can change independently of the other items. This means a few things:

  • Values that represent the same thing cannot be duplicated, such that updating one requires the update of another.

  • Values that have more than one presentation (like domain names vs ip addresses) should have only presentation within the configuration approach. It might be ok to use an IP address or a host name, but you don't include both.

These ideas are easy to implement for "atomic" values, where one value is clearly independent of the others; however, these ideas are harder to implement for "compound" values, where one value is part of another value. For example, a JDBC database connection string can be represented in two ways; as a single string or as a compound collection of protocol, database driver id, hostname, port, database name, connection options, etc.

The latter way makes it easy to change the hostname; but, when you decide to change the database driver id, you notice that the default port will likely have to change to match the database driver id. The default port is not orthogonal to the database driver id. Yes, the port (if specified) can be changed independently, but the update pattern is such that nearly every time one needs to change the database driver id, the port will also have to be verified.

Assuming one took the compositional approach, this means the driver id and the port are not orthogonal settings. If one took the connection string approach, then there is only one setting, so it is by definition independent and orthogonal.

Now, assuming you took the connection string approach. The database driver (was) typically loaded by class name, which isn't embedded in the connection URL (string). If you specified the class name in a different environmental variable, the two are clearly not orthogonal. This means you cannot choose the single string JDBC_URL and a DRIVER_NAME set of variables and strictly adhere to "orthogonal" configuration. Thankfully, there are other approaches.

One can pre-parse the JDBC connection URL, pulling out the driver id, and then use a lookup table to find the class name, and preload the class. This would remove the need for two non-orthogonal settings, at the cost of having a bit of convenience utility code.

Edwin Buck
  • 489
  • 3
  • 7