1- Shield away from dependencies. Use languages that are robust (no JS, no PHP) and if possible, generate native .exes (Delphi, Rust, Go,...).
Langs with large runtime/deps (Java, .NET, Js) are always trouble in the long run. I re-enter with .NET Core and have regretted heavily it (because maintenance, not performance or dev productivity).
ie: If a lang/tool/ecosystem is for large teams (java, .net, c++), is not for zero maintenance.
How easy is to setup and get running something (without resort to auto-installers or docker images) is a high evidence in how good will be for this metric.
2- If possible (mobile) use iOS. Android is not robust at all for long term prospects
I made a enterprise iOS app that is also nearly worry-free. My only job is to upgrade xcode and recompile from time to time.
I enter android late in the game, dreaming that android become more or less good. Not.
3- Important! If possible, split the programas between what could be "zero maintenance" and high maintenance.
I have made one in Delphi that is running 10 years in some places with zero calls after the first 3 years of tweaking.
Is split in 2 parts: The Delphi side have stay solid, and
the "business" side that requiere more changes are in scripts in python that I integrate with the Delphi side.
Even the python side is now near worry free, but I need to do changes here and there.
4- If need JS, pick VERY carefully how use it. JS is the anti-tesis of zero maintenance. The web is hostile in this area. You could lower damage if VERY carefully know what to use.
5- Stay away of stupid "is for scalability" traps. Micro-services, nosql and similar are the best way to destroy productivity. Modular code yet running in a monolithic (or maybe in a REST api + client) will be more than enough by long margins when coupled with postgresql or sqlite. Again, a solid RDBMS is what most need. "Eventual" consistency is a stupid choice most of time.
P.D: I'm solo developer, and have not time or high pay to cover for bad choices, so i try to perform very well in this metric.
You can't use mobile at all. Apple requires you to update your app every year to support their new tooling. Just in iOS 13, if your app uses FB login, you need to add Apple Login.
Or, every year, you need to re-generated and update your push notification certificates.
Apple releases a new iPhone and then you have to update your marketing images in the iOS store with the new pixel dimensions. Its never ending.
????. I barely do this each 2 or 3 years. Also, I keep away to high dependencies, so maybe I get lucky.
I do small stuff like
- re-generated and update your push notification certificates.
- update your marketing images
once per year? That is so close to zero maintenance as is possible to get.
>Starting April, 2020, all iPhone and iPad apps submitted to the App Store will need to be built with the iOS 13 SDK or later. They must also support the all-screen design of iPhone XS Max or the 12.9-inch iPad Pro (3rd generation), or later.
If you want to properly support iOS 13, that also means implementing dark mode support and breaking your application delegate apart to a scene delegate for multiple instances. In addition to the notched screen "safe area" changes that most developers have probably caught up on by now but are becoming mandatory.
Previous years it's meant supporting flexible sizes for new devices, sizes for split screen multitasking, drag and drop, siri intents, adding @3x retina assets, changing out UIWebView to the (not directly compatible) WKWebView, and a million other things.
For a simple app with minimal support for iOS's growing featureset, maybe some years you can get away with loading it into this year's XCode, clicking the automatic code update button, and compiling. But polished iOS apps put a lot more work into keeping up.
I don't have any knowledge of how Android compares, but iOS is definitely a moving target and Apple isn't afraid of deprecating things or mandating support for newer features.
Compare that to a static site with Netlify or AWS S3, which never requires an annual package update and rebuild.
You also didn't address how Apple requires you to update the marketing screen captures. You will need to brush off the dust of your faked out app data and spend a few hours tweaking them in an image editor.
Also don't do that (social login etc), if you want low maintenance.
I coded that to run in every browser I could get my hands on. Browsers of the last 10 years have been very good at maintaining backwards compatibility, so no updates needed, at all. They may rewrite the OS cores from scratch (or in Scratch) and replace all the current instruction sets, browser vendors may come and go, and new features will keep on being added, but none of that will break my game.
JS today is a bigger mess. Is possible to avoid problems
I use vue, without npm, package managers or anything else than direct link in the head. But I need to be care-full in what to code and check support across browsers.
About "not robust". In fact what need to be defended is how is possible to call it robust!
But anyway: JS is a badly designed language, have weird edge cases, and will fail silently (the worst of all) in many ways.
A robust language not only catch stupid errors, but have a better std support (like having integers!) and better defaults and ways to do data transformations.
Exe is exactly what I think of when I think of bitrot though. None of the games from my childhood can run on a modern OS.
If you're running js or python etc, even if the interpreters are no longer widely available in the future, people using your code can still try to port it themselves (instead of demanding that you support them throughout the eons).
For Win32 pretty much anything can be made to work with Windows' own compatibility settings, dgVoodoo2 (for games) and minor tweaks. I have many applications and games from the 90s and 2000s, both in digital and physical form and the only issue i face to make them run in modern Windows 10 is the DRM some games in the mid-2000s had (i avoid anything with DRM nowadays).
For 16bit Windows on 64bit OTVDM (https://github.com/otya128/OTVDM) should make most stuff work (especially games). This is also great for installers.
For DOS, DOSBox for games and vDos for applications should run pretty much anything better than when they were new. DOSBox also works if you have Windows 3.1 installed. Yeah these aren't exactly native (vDos does try to use some OS services though) but the UX is pretty much the same with what you'd get even back in the 16bit Windows days when trying to run a DOS application.
I have never had something not work and then work after running in compatibility mode.
When I've (had to use Windows and) had reason to try it, I've tried every OS in the list and ended up thinking it's just a dummy wrapper that doesn't do anything included to make you feel better about Windows but think the program really is a lost cause after all.
I don't think that's within the time horizons that OP is trying to consider. That's kind of like saying "no one (or very few people with great effort) can read the books that we wrote in the middle ages!"
Low maintenance simply means they can afford to give a few months to shut down a service rather than the next day.
If you know what you are doing you can write zero dependency code that works well with old and modern browsers alike. This isn't as hard as it sounds either.
Especially with solid API's like with Cloudflare Workers V8 variant.
Admittedly, it's not a huge application but there's nothing in principle that would preclude a more complex application.
The use of const prevents Internet Explorer up to IE 10 to run the application but that's a small trade-off I was willing to make in favour of more robust code.
Having no understanding of the DOM and the standard APIs then writing without dependencies might take 1000x longer. I was assuming a competent developer when I mentioned this isn’t that hard.
I have found well written PHP code requires very little unplanned maintenance. When I package the application in a docker container along with its dependencies and a webserver (nginx), I find that I can run a PHP application for years without having to worry about it.
In this sense, PHP code can be very robust in the sense that there are little surprises once the application goes into production. The PHP ecosystem is very mature.
Every year I go back to visit the url, it works flawlessly with latest content. They even didn't bothered to change admin creds till 2017.
Site is still up and running
if the goal is to maintain an application and catch issues at compile time. go with a better type system Haskell/Ocaml/Rust.
Another option would be to use generative testing where you have tight control over what gets in, for example, Clojure/Spec.
But there ARE some ancient things in Java that are being deprecated. Or moved out to separate libraries not bundled into the JRE.
I would also point out that with Docker you could package every possible dependency into the container. The container is now portable and has no dependencies outside of what is packaged in the container. To the user, they don't care what technology or Rube-Goldberg contraptions exist within the container.
Also see AppImage.
* bundled xerces around 1.6, breaking apps that also carried their own xerces
* removed sun.misc.Unsafe from v11, breaking legit apps the apps that use off-heap memory
* sun and later oracle made everything to make applets useless, creating ridiculous security requirements and no clear way for a user to whitelist trusted applets. same for java web start. they had no problem disabling MD5 and RSA in their SSL impl, breaking the old clients.
Every part of the stack will need maintenance every now and then. Some parts even introduce breaking changes and force you to alter your own code. The slimmer the stack, the less often you have to fix it. And the less often you have to fix or refactor your application.
2: A stack that values stability
Linux is a good example. Linus Torvald: "We do not break userspace!"
PHP is a another one. The core developers rarely introduce breaking changes. And when they plan to do so, there is usually an intense fight over it.
3: Acceptance Testing
In the simplest form that means sending http requests to your web application and check if it returns the expected output. In my experience, acceptance tests find more real world issues then unit tests.
4: Write less code
Writing the same functionality with less code has multiple advantages. One of them is that it will break less often. Much more could be said about it. Paul Graham brings up the value of terseness frequently:
Less is more. This is actually one of the reasons why I named my account no_gravity.
> Linux is a good example. Linus Torvald: "We do not break userspace!"
Sadly the people making things in userspace don't seem to mind breaking it frequently.
* sqlite says it's "zero maintenance" because nobody has to keep a database server running, and your .sqlite3 files don't need a defragmentation step or similar.
* There are middlewares like RabbitMQ where an upgrade through the OS installer generally Just Works [TM], no additional steps necessary. Yet somebody should monitor the RabbitMQ instance, just in case the service does go down, or reaches resource limits
* There are tools that have very limited scope and API surface to stay stable for a looong time, those are also kinda "zero maintenance".
In my experience, all serious business applications that automate workflows or otherwise create value do need some kind of regular maintenance.
Depending on the installation base and maintenance effort, striving for zero maintenance might not be cost effective.
> How do you as a developer, not become a lifetime maintaimer?
A maintainer is a developer.
Depending on the project, things you can do if you don't want to burden yourself with maintenance:
* Build a community around the project, and hand maintenance to the community
* abandon a project
* leave lots of documentation that makes it easy for others to maintain it
* pay somebody to maintain it
* work as a consultant/contractor, and fire the client after the initial development phase (might not be the best for your reputation, could be OK if you are up-front about it and make a very good handoff).
* If most of the maintenance is keeping it up at all, engineer for availability over consistency (if applicable to the business domain).
* Accept that maintenance is part of the normal lifecycle
The appropriate strategies highly depend on the kind of project.
They do benefit from a VACUUM from time to time .
I spent quite a bit of time getting it off the ground, but over the last 2 years, I've spent maybe ~10 hours in total keeping it running.
The only times when I've had to invest time into it, is when a certain piece of my tech stack gets deprecated or discontinued. For example, I had originally done login-auth through a SaaS provider, which then got acquired by a larger company which discontinued their API. I then had to go through their migration process to keep the site running. However, the above doesn't happen all that often, especially if you choose stable technologies and companies.
Besides that, I had consciously designed the site to be completely free of manual maintenance, even if it involved more upfront costs. Examples:
- Going serverless via Heroku
- Using SaaS services like RDS, S3, SendGrid etc
- Using scripts and cron-jobs/heroku-schedulers to automate anything that needs periodic maintenance
- Relying on "push" alerts as opposed to "polling" alerts. Ie, when something goes wrong, your server should notify you immediately. Instead of waiting for you to periodically check some dashboard
More details: https://software.rajivprab.com/2018/04/29/caucus-tech-stack/
First one is taking OS updates that are security critical - as anytime you take an update theres a chance something somewhere gets broken.
Second one is AWS instances themselves being switched. From time to time (very infrequently in my experience) Amazon will send you an email indicating your EC2 instance is being migrated to a new physical host and to initiate this you must manually restart your instance.
As for the rest, a script in root's crontab that does:
1 - Delete log files older than X (because running out of disk space is not a good situation)
2 - Hit Lets Encrypt for new certs if necessary ( because expired certs give a lousy customer experience)
3 - Preemptively bounce any application servers (Nginx, PHP FPM, Tomcat, what have you )
4 - Setup all hosts such that your critical software restarts at boot time in the event of an unexpected reboot situation (gives you the ability to cron schedule nightly reboot command)
* If you're running any database regardless of where, be sure you allocated enough space that you don't end up running out of database storage
* Implement some downtime monitoring to tell you when there are issues
* It's a good practice to be changing passwords on any authenticated resource at some interval too
The practices listed here (off the top of my head - not an all inclusive list) are about as close as I attempt to get to Zero Maintenance myself. Customers pay for systems to be developed and they should expect some level of ongoing care and feeding as entropy is pervasive.
But its a good excuse to sell your customers a maintenance contract right?
Do you mind explaining this?
The blessing and curse of software is it's mutability.
1) Make everything static, HTML, CSS, don't manage your own servers
2) Use as few dependencies as possible when dealing with JS
2 a) For backend try to find a service that do the work for you without you deploying your servers
2 b) Maybe cloud functions are enough?
3) Write tests
4) Don't write bugs :D
5) Setup alerts (uptime robot)
I generally agree, but eventually you're gonna start getting emails saying things like "We're deprecating Node 8.x in our Lambda / Cloudfunction / etc"
There are only three reasons I've been drawn into some projects:
1) A bug occurs and needs to be fixed
2) An external dependency breaks something
- Write tests and/or have high confidence in code/infrastructure behavior (using tools you know really well helps). Avoid cognitive complexity in code constructs aggressively.
- Limit integration w/ 3rd parties EXCEPT the ones that reduce your goal of zero-maintenance.
- Create interfaces/tooling which make automating tasks easy.
- Get notified when things break
This all assumes your application is like most being built these days: you're using a framework on the web. If you put your application on a machine that never is exposed to the web, or you create an application with zero dependencies (including OS-level dependencies) you might get away with never updating it.
So to avoid any maintenance, minimize - code, complexity and all dependency and use a language and platform that can last a few years. Essentially, in today's world this will be very difficult and doing this will also cost you development time, there is no easy way around it.
For example, you can build your whole app in Clojure, which is rock solid and stable, but even then you will have to patch the OS, JVM, DB etc. With traffic changes you will have to scale up / down.
It is a Debian-powered machine, not connected to internet, which is performing various tasks and controlling some hardware. The software running on it was built 6 years ago in C++ and using OpenCV and CUDA.
The machine powers on and off itself on a specific routine due to on-site checks.
It clears old logs automatically if older than X days or bigger than Y MBytes.
Until today, no software or hardware failure occurred. The whole disk is snapshotted with dd command. If hard drive failures occur, it's easy to swap it and start again.
To decrease maintenance, generally you want to reduce your dependence on external services that might change, minimise the use of complex third party libraries that might have security problems later, and keep your app as simple as you can to reduce the chance of bugs.
It's hard to predict what changes are going to be required for a given ecosystem (e.g. Android, Mac, Chrome Web Store, web browsers) so sometimes it's a matter of luck unless you can guarantee the OS, hardware, APIs etc. are never going to change.
I'm currently working on a Chrome extension (https://www.checkbot.io) that doesn't require a lot of essential maintenance besides keeping up with changes Google have been making to make extensions more secure. Bracing myself for what breaking Manifest v3 changes are announced.
Apps can not be zero maintenance by definition. Apps are literally alive, apps mature, evolve, get older, there will always be some kind of maintenance. As world changes, apps change with it.
If ZERO maintenance is a HARD requirement, then think about total isolation. No packaging, and NO ENVIRONMENT CHANGES. With constant, isolated env, it is possible to have a minimal maintenance app.
Another argument that Agile can not be a hammer for every nail. Common sense with project management and architecture is extremely important.
Don't plan for an application to live for more than five years, especially v1. Put enough work into architecture and maintainability to be able to throw it out and redevelop after five years. Be clear about this upfront. In five years' time you won't even be able to find devs to maintain what was developed today.
In order to 'maintain' an application properly business needs to keep investing in modernization of the application, which is more than just maintenance. Let's say they need to invest 30% of the original cost per year. Most will not do that saying 'It is a capital asset that I paid for and it should work as expected for as long as I need it' - okay but in five years time it will be so out of date that it will need to be redeveloped.
No. The only code that requires no maintenance is the code you do not write. In other words, "No code is easier to maintain than no code." Add that to the nihilist coding attributes:
No code runs faster than no code.
No code has fewer bugs than no code.
No code uses less memory than no code.
No code is easier to understand than no code.
No code is easier to maintain than no code.
The actual effort required to maintain the code will vary depending on what the code does, the environment the code runs in, and the needs of the code's end users.
Unmaintained code will ultimately fail the same way that all other things that humans build do. If someone does not maintain the code, it will eventually degrade and fail.
Anytime you write code, especially for a long-lasting endeavour, you should consider how the code you write will be maintained and what might cause it to fail sooner than expected.
I also have a maintenance contract for one of these: https://arsandbox.ucdavis.edu/
It turns itself off at night and back on in the morning. 3 years running now without touching it once, used by hundreds of people daily.
Entrepreneurs occasionally ask me to take their idea and make it a reality. Their most common request is for me to build them a website so that they can sell stuff. Sure, I could take their money and build it, but it's much better for them to sell on an existing e-commerce site or learn how to use a CMS.
1. Don’t use a build system. Use scripting language that comes preinstalled on Debian / Ubuntu. Peel 5 is still my weapon of choice for robust small web apps. Look at python too.
2. Avoid JS / Ajax. I can bet that security restrictions will break it in the future, however good old form POST works still pretty good.
3. Use own hardware. Raspberry PI with HDD or some banana PI works quite allright. Also provisioning is easy by keeping a copy of your image.
4. Don’t use managed services. Use database on the very same machine that you host the app itself. Backup is an extra step you can achieve via those, but don’t use External service, since it will most probably break.
I think it's being nitpicky for the purposes of this discussion but I think there are probably several HNers who could tell you about how their product hosted in AWS went down because of a credit card issue.
Otherwise this is definitely the way to go. Nothing beats static files that you can just cp into a bucket.
If you don't want to be a lifetime maintainer, then you have to transfer ownership to someone else or consider the project to have reached its end of support.
Consider an analogy to building houses, it may appear that the builder has finished their job since the house is fully constructed, but like any system, it requires maintenance for the entire duration of its lifetime.
Systems degrade over time without maintenance.
Seriously speaking the following things help alot:
1.Reduce external dependencies. The less integration with 3rd party apis and services the less maintenance you will be doing.
2. Reduce external dependencies.
3. Reduce external dependencies.
4. Unit Tests
5. Integration Tests
6. End to End Tests
7. Reduce external dependencies.
1. KISS, keep it simple, stupid.
Keep your code as simple and straight forward as possible. You can do that in a few ways:
- As others have said, focus on keeping dependencies to a minimum. This can include libraries but also other 3rd party vendors/external apis.
- try to keep feature creep out. the more complex the codebase the more likely it is to suffer failures. Keep things focused on solving specific problems.
2. Build software that is meant to be delegated.
You can't remove all dependencies. Whether its libraries, external apis, or hosting, every piece of software needs something to run. If you don't want to be stuck as a lifetime maintainer, then you'll need to ensure your code can run without you. There are many ways to do this:
- use existing, well tasted, stable technology that is supported and maintained by your org, not something new and fancy for each project.
- enlist others to help early on, sys admins, hosting providers, or whomever. Build your software in a way that is supported by those providers.
* Hosted on Heroku, which gets you continuous deployment and Let’s Encrypt
* Completely automated, even the smallest manual task
* Low traffic, which may be the most important. Apps with large and growing user bases are very difficult to manage hands-off.
Anything that depends on other stuff really is susceptible to changes and needed maintenance.
2. Develop tools which allows end-users to adjust the software, make as many settings as possible.
I don't think that those options are actually good in the end. If your software is tolerable to the wrong input, it might just work wrong and nobody will notice it. If there are too many options, nobody will know all of them and in the end they'll either ask you or configure it wrong. If you'll have too much of flexibility, then developers who will need to extend your software, will be forced to work bounded by inevitable restrictions.
I like software that's precise and does only one kind of thing. It crashes on wrong input, so I can either blame someone who's responsible for wrong input (I mean service, not ordinary user) or fix software. It must not be flexible, but it should have flexible architecture so I can just adjust or extend code to adapt it as necessary.
You haven't provided enough context here, but since we even patch software on Mars I doubt you can built a bug free, feature complete software that will last "forever", so you'll need to find ways to delegate maintenance to someone else.
If it is more complicated than that ( i.e. must do several things very well with ever-changing needs ), document it clearly and include a link to the source code and build instructions.
Perhaps this should be elevated to "Burnam's Law".
But the odds of something that simple meeting your goals is unlikely.
And have no outside integration other than the most common of protocols.
So program defensively and expect to have to do the occasional bit of maintenance.
An application with zero maintenance means that it either has a very, very targeted function that doesn't change, or it isn't being used after a certain period of time.
- Never upgrade
- Cloudflare for SSL
Overall stick with technologies that have been around for a long time and have proven themselves to be stable and their developers do value stability. Sadly most developers prefer to run fast and break things, regardless of tech, so your options will be limited. Also avoid anything latest, greatest, shiny and new - even if their developers promise stability, at least for the initial versions until the tech matures a bit.
If you see anything that uses semver run away. Semver might sound like a good idea on the surface in that any breaking change means increasing a major version. But the flip side of that coin is that by choosing semver the developers communicate that they do plan on breaking backwards compatibility at some point. Despite the excuses a lot of semver enthusiasts will tell you, there are very very VERY few reasons to break backwards compatibility and the vast vast majority of them are imposed from outside (e.g. the sort where your OS drops 32bit support and there isn't anything you can do about it or the architecture you were relying on isn't supported by anyone anymore).
On the desktop stick with languages that either have multiple independent implementations (independent not only in terms of who developers it, but also in terms of codebase) based on a standard, like C and C++. This way you can switch between implementations in case something goes bad. Also do not use the latest versions of the standard unless every implementation (and by "every" i mean "really, truly, every" not just the popular ones) implements it with more or less the same features (stick with the least implemented ones). This gives you a greater set of choices to switch when you decide to switch.
For desktop UI on Windows use the Win32 API or roll your own. If you plan on being cross platform, roll your own anyway since the only thing you can rely on (at least for the foreseeable future) on Linux is X11 - anything else is bound to break and/or not exist in your users' computers. Note that if you also plan on supporting macOS rolling your own may not be liked over there and you should seriously consider if it is worth the hassle since as Apple has proven many times they do not care about backwards compatibility so you'll need to maintain your app regardless (though you can try and minimize that to just a recompile).
For web i do not know much, but i'd stick with stuff that do not break. PHP and Java seem stable. Client-side things tend to be very stable though Google does give me the impression that they'd like to flex their muscle to drop some stuff they consider "bad".
For mobile abandon all hope, it is the most ephemeral platform.
Beyond that, make either very small programs that you can easily modify or make modular programs that you can swap out things without much hassle.
Personally i work with desktop. For my own stuff i stick with C89 and Free Pascal. The former doesn't change, the latter does change but very very infrequently and it is all statically compiled anyway so assuming the underlying stuff do not change they'll work. Lazarus on Linux will eventually be an issue because Gtk2, but there isn't much that can be done about that (the author of FPGUI - that only relies on X11 - says that it can be used with the LCL FPGUI backend, but personally i haven't tried it and i think the backend isn't very mature). Win32 stuff is practically eternal (and funnily enough on Linux Win32 via Wine is the stablest ABI - essentially making x86+Win32+C89 the most stable combo even if Microsoft drops it :-P).