Software Maintenance - Thinking in Decades

Not so long ago, I had the opportunity to spend a brief period working in the "aviation" industry. A sign with the slogan "Old school" was attached to the door of my office, and the product my collegue and I were working on had a maintenance period and life-span of 30 years. Three decades!

Think about it for a moment. What kind of software did you develop back in 1996? What kind of compiler were you using? On which operating system? And which of these software systems are still available as of today in 2026? And, would your software still compile or run?

For me, back in 1996, it was Watcom C++ on Windows 95, as far as I can remember, likely on an Intel Pentium system with 166 MHz that I bought from Arlt. In order to resurrect such a system, you'd likely set up things in a Virtual Machine today. While getting at hand of an old CD-ROM of Windows 95 wouldn't be that hard, would you still get the binaries of the compiler?

Some tips and tricks

If you plan to maintain your software for the upcoming 30 years, here are my suggestions for you.

Use "old-school" technology

Use technology which was already in use 20 years ago. Chances are high that - if it still works today - it will continue to work for the coming 30 years.

As an example, I chose to use server-side rendered HTML instead of a fancy Javascript Single Page Application (SPA) framework.

As HTTP server, I employed the embedded C/C++ webserver Civetweb, which has a nice and clean API, and which I already used 2016 inside a real-time operating system kernel.

The CSS I wrote by hand and tried to keep it minimal. Bootstrap would have looked much nicer of course, but would have added more maintenance work in the future.

Some of these decisions also greatly helped with the limitations and restrictions I had at my work place. Don't laugh, but I often tested the web application using the console-based w3m browser or graphical browser dillo due to heavy network lags and because Firefox was no longer distributed as Debian package (the Debian package tells you to use snap, which was blocked).

Stay away from Javascript

Kids, don't play with fire! Stay away from Javascript!

While Javascript will likely be still around in 30 years, the dependencies you are using today will not.

And good luck with using Javascript without npm. Or good luck with supply-chain attacks when using npm.

Stay away from package managers

At my work place, most package repositories were blocked by default, due to security considerations. No Go packages. No Python packages. No NPM packages. No Ruby gems. No Rust crates. Only stable Debian packages and whatever git repo is available on github.

With that restriction, try to develop even the smallest program in any of these shiny new, dependency-rich languages. Good luck!

And one thing that you definitively don't want to do is: Maintaining software for the next 30 years that has 1742 direct or indirect dependencies (hint: goodbye Javascript).

Stay away from software with lots of indirect dependencies

It is a maintenance nightmare. Just don't do it.

What you really want is to have all the source code required to build your software to be stored ("vendored") within your own repository.

Make it easy to build your software

Anything more than gmake build is a failure.

Build your software on an arcane build server

At least 10 years old. Use a Linux distro different from your development machine.

In my case, I discovered the existence of the arcane build server a bit late in the development cycle, at a time when I had already intensively used Meson as build system. Of course, that arcance build server's Meson version was very outdated and wasn't even working properly due to a Python version mismatch. This forced me to rewrite the build system using GNU make.

Be assured that any fancy build-system abstraction will lead to maintenance issues in 10, 20 or 30 years. Be assured that Python 3 code will no longer run unmodified on Python 5.

Use Docker as a tool, not as a dependency

Docker is nice tool. But it's the last thing you ever want to depend on in order to build your software. If your software doesn't build without Docker, I consider it a complete failure!

In my case, I provided a Dockerfile and added an optional build target build-container to reproducibly build the software within a container as convenience. It would just invoke gmake build within a well-defined container.

Use scheduled yearly builds

Continuous Integration (CI) often isn't a known term in some industries. But that's not an issue at all. All it needs is a scheduled yearly build to catch problems "early". This has to be communicated with the management in order to survive employee turnover.

It's better to fix small issues every year than to wait for 25 years and then run into massive issues. This also keeps the knowledge alive.

Stay away from any sort of complexity

KISS - Keep it simple, stupid.

Use a language that is older than 30 years

Not only are the chances higher that these languages will be still alive in 10 or 20 years, but it is also easier to predict the future of a languge by knowing it's past.

Also take volatility and backwards-breaking changes that happened in the past into account. For example, Python doesn't score very well in that regard.

Use a language that you can build from source

And use a simple test: Download the source code of that language from 30 years ago and try to build it with today's compilers. If you run into severe problems, stay away for that language.

Use a language backed by an industry standard

And that basically means, stick with C or C++.

While C is so much better when it comes to long-term maintainability, C++ unfortunately is the defacto industry standard. C code adhering to a standard will continue to build unmodified in 30 years, while your C++ code will likely see warnings or maybe even compiler errors when newer compilers pop up.

If you have the choice, stick with C. Amen.