{"article":{"slug":"the-geometric-model-of-maintenance","title":"The geometric model of maintenance","subtitle":null,"summary":"Using git history labelled as new development or maintenance, kqr tests James Shore's rule that each person-month of code induces 10 days of maintenance in year one and 5 days a year after, finds it does not track real projects like tmux, and proposes a geometrically decaying model whose fitted totals range from about 1.5x maintenance per unit of new work for nginx to 5.3x for Neovim.","content_type":"research","language":"en","canonical_url":"https://entropicthoughts.com/geometric-model-of-maintenance","author":{"name":"kqr","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Entropic Thoughts","url":"https://entropicthoughts.com/","listing_slug":null,"listing":null},"topics":[{"name":"Software Engineering","slug":"software-engineering","url":"https://listedarticles.com/topics/software-engineering"},{"name":"Statistics","slug":"statistics","url":"https://listedarticles.com/topics/statistics"},{"name":"Programming","slug":"programming","url":"https://listedarticles.com/topics/programming"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":2827,"reading_minutes":12,"published_at":"2026-10-13T00:00:00.000Z","added_at":"2026-10-15T14:19:01.056Z","updated_at":"2026-10-15T14:19:01.056Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":true},"profile_url":"https://listedarticles.com/articles/the-geometric-model-of-maintenance","markdown_url":"https://listedarticles.com/articles/the-geometric-model-of-maintenance.md","example":false,"citation":"kqr, Entropic Thoughts. \"The geometric model of maintenance.\" 13 Oct 2026. https://entropicthoughts.com/geometric-model-of-maintenance (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://entropicthoughts.com/geometric-model-of-maintenance"},"body_markdown":"James Shore posits that [each person-month spent writing code results in 10 days\nof maintenance](https://www.jamesshore.com/v2/blog/2026/you-need-ai-that-reduces-your-maintenance-costs) in the first year, then 5 days every year after that. Naïvely\ninterpreted, this is a *threshold*-based model for induced maintenance, and its\ninteresting because it’s so simple.\n\nIf it could be shown to be true, that’d be useful. The argument Shore is\nmaking about the effects of robot-generated code does not depend on the specific\nnumbers, so Shore’s numbers come from a hypothetical wisdom-of-the-crowds\naggregation rather than concrete data. But no hypotheticals are necessary here.\nWe have a thing called git.\n\n# Testing the threshold model of maintenance\n\nLet’s say [we have a way of labeling each commit](https://entropicthoughts.com/cheaper-llm-labeling) as either “new development” or\n“maintenance”. Then we can count how many commits of each type there are in a\nmonth.[1] Possibly better, we can count [how much\ncomplexity has been handled](https://entropicthoughts.com/lines-of-code) in a month.[2]\n\nThe following plot shows the cumulative effort that has gone into the\ndevelopment of tmux since its beginning to the day I start writing this article.\n\n![induced-maintenance-demand-01.svg](https://entropicthoughts.com/image/induced-maintenance-demand-01.svg)\n\nWe will look first at the black curve, which represents effort spent adding\nfeatures to tmux. From left to right:\n\n- In the first month of the repository, a few thousand lines of feature work are\n  present almost from the start.\n- From the start in 2008 to 2010, tmux saw rather intense activity at\n  around 30,000 lines of new development effort per year.\n- Then new development slowed down, and between 2010 and 2026, it happened at a\n  fairly steady pace of 8,000 lines of effort per year.\n- As of today, tmux stands at just over 230,000 lines of effort of new\n  development that have happened throughout its history.\n\nTo see how much effort has been spent on maintenance, we perform the same\nexercise but with the red curve instead.\n\n- Maintenance started dipping behind new development early on, but then traced\n  fairly closely to new development between 2008 and 2014.\n- After that, maintenance took off at a rate of 30,000 lines of effort per year,\n  continuing at that pace until 2022.\n- Then it slowed down again to around 10,000 lines of effort per year.\n- As of today, tmux has required around 430,000 lines of effort for maintenance.\n\nIn other words, of the total roughly 660,000 lines of effort spent on tmux, only\nabout a third has been on new development. This has changed over time, and we\ncan find roughly four regimes in the project’s history.\n\n- 2008–2010: Total effort is 60,000 lines per year. About 50 % of that is maintenance.\n- 2010–2014: Total effort is 16,000 lines per year. About 50 % of that is\n  maintenance.\n- 2014–2022: Total effort is 38,000 lines per year. About 80 % of that is\n  maintenance.\n- 2022–2026: Total effort is 18,000 lines per year. About 55 % of that is\n  maintenance.\n\nThis is not quite the continuous increase of maintenance fraction predicted by\nthe threshold model. To be sure, we should also check visually. The prediction\nof the threshold model is represented by the dotted red line.[3]\n\n![induced-maintenance-demand-02.svg](https://entropicthoughts.com/image/induced-maintenance-demand-02.svg)\n\nAll the way from 2008 to 2022, the simple threshold model does actually fairly\nclosely predict the amount of maintenance tmux has required. But the exponential\nnature of the threshold model means its prediction eventually goes up faster\nthan actual maintenance performed.[4] This means the model fit will likely worsen as time goes on.\n\nThe threshold model is also not a great fit for some other projects, where it\ngenerally overestimates the amount of maintenance performed. As one example,\nmaintenance work has made up 63 % of the effort spent on nginx to date, but the\nthreshold model suggests it should be 81 %. Other projects where the model\noverestimates the maintenance requirements are Rust, VSCode, and Go.\n\nIn contrast, the model underestimates the amount of maintenance required for\nNeovim. The Neovim project has been maintenance-heavy from the start, and\nthrough its history, 83 % of the work on Neovim has been maintenance, but the\nthreshold model suggests it should be 70 %.\n\nHowever, the more general problem with the threshold model is one of timing. This is\nbest illustrated with Syncthing.\n\n![induced-maintenance-demand-03.svg](https://entropicthoughts.com/image/induced-maintenance-demand-03.svg)\n\nThe threshold model lands close to the correct lifetime maintenance fraction\nhere (70 % vs. the real 67 %) but it is nowhere near following the actual maintenance\ncurve.\n\nAn apologist could argue that the lack of curve-following is not because the\nmodel is wrong, but because the Syncthing project is an outlier that decided to\nfront-load a bunch of maintenance. Unfortunately, Syncthing isn’t the only\nproject where this happens, and it’s actually a symptom of the big flaw of the\nthreshold model. Given a constant level of new feature development, it predicts\nmaintenance will grow exponentially.[5] That doesn’t seem to be what happens in practise in the\nprojects I’ve looked at.\n\n# A geometric model\n\nBut maybe we can rescue the model by refining it. The original threshold model\nsays that the 100 lines of effort I spend on new development today contributes\nat least 5 lines of maintenance effort per year until infinity. That’s probably\nnot true, in part because old code tends to be more stable, but also because\ncode is gradually rewritten, so the 100 lines I made today might not even be\naround five years from now.\n\nWe can tweak the threshold model to account for this, by adopting a geometric\ndecay on the maintenance induced by new development. If we pick numbers\nconsistent with what Shore proposed, we’d say that maintenance starts at 5 % of\nthe work performed[6], and decays\nwith 3.6 % per month.[7] However, these numbers\nwould yield results very similar to what we’ve already seen: the maintenance\ncurve doesn’t track actual maintenance performed.\n\nHowever, we can pick other numbers. For example, if maintenance starts at 4 % of\nthe work performed, and decays with 2.6 % per month, we get a maintenance curve\nthat tracks fairly closely to the new development curve. This happens to work\nwell for nginx, which is light on maintenance:\n\n![induced-maintenance-demand-04.svg](https://entropicthoughts.com/image/induced-maintenance-demand-04.svg)\n\nFor a project that needs more maintenance, like tmux, the same numbers don’t\nwork. They produce a curve that underestimates the maintenance required.\n\n![induced-maintenance-demand-05.svg](https://entropicthoughts.com/image/induced-maintenance-demand-05.svg)\n\nWe can ask our computer to pick out the numbers that produce the\noptimally-fitting modified geometric curve for tmux. This happens at the same 4 %\ninitial value, but decaying with 1.4 % instead of 2.6 %. Here it is,\ngraphically:\n\n![induced-maintenance-demand-06.svg](https://entropicthoughts.com/image/induced-maintenance-demand-06.svg)\n\nIf we continue to do this for all projects we have data for, we get a set of\nnumbers with large variation.\n\n| Project | Up-front maintenance | Decay |\n| --- | --- | --- |\n| nginx | 4 % | 2.6 % |\n| tmux | 4 % | 1.4 % |\n| Neovim | 20 % | 3.8 % |\n| Syncthing | 29 % | 14 % |\n| React Native | 7 % | 3.2 % |\n| Go | 3 % | 0.7 % |\n| VSCode | 48 % | 19 % |\n| Rust | 12 % | 3.6 % |\n\nThese numbers are not intended to tell us anything causal about how maintenance\ncomes to be. Rather, they’re the *just-so* numbers we are forced to pick to make\nthe geometric curve follow the actual maintenance performed closely, for each project.\n\nWe can take these numbers and extend the maintenance curve ten years into the\nfuture, and predict how much maintenance will be needed in these projects even\nif they completely stop all new development. Here’s nginx.\n\n![induced-maintenance-demand-07.svg](https://entropicthoughts.com/image/induced-maintenance-demand-07.svg)\n\nThe curve illustrates that nginx is already fairly close to their current\nmaintenance saturation point, and rather little maintenance remains if they\nfreeze all new development now. We can contrast this with something like tmux,\nwhich, when extended a decade forward, has a long way to go until their\nmaintenance curve plateaus.\n\n![induced-maintenance-demand-08.svg](https://entropicthoughts.com/image/induced-maintenance-demand-08.svg)\n\nAlthough it’s neat to be able to reproduce maintenance curves for projects, we\nshouldn’t really project these curves into the future because that gives viewers\nthe idea that the curves are predictive, when in reality they should be thought\nof as descriptive. But! These plots indicate that maybe there’s a more\nhuman-friendly way to present the numbers, that say something more intuitive\nabout the projects.\n\n# The geometric model to characterise projects\n\nHere’s one way to interpret the numbers of the geometric model. With a\ngeometrically decaying series, the sum of all numbers is computed by dividing\nthe starting value by the decay factor. The sum, in this case, represents the\ntotal amount of maintenance performed relative to the new development effort.\n\n| Project | Total maintenance |\n| --- | --- |\n| nginx | 1.5× |\n| Syncthing | 2.0× |\n| React Native | 2.1× |\n| VSCode | 2.5× |\n| tmux | 2.6× |\n| Rust | 3.2× |\n| Go | 4.3× |\n| Neovim | 5.3× |\n\nThis is *so interesting*. According to the geometric model, each hour of\nnew development on nginx produces 1.5 more hours of maintenance work over the\nlifetime of the project. That is the lowest figure of these projects. It could\nmean that\n\n- The nginx developers only accept high-quality code, since it needs so little\n  maintenance going forward, or\n- nginx runs in fairly predictable environments where few assumptions can be\n  incorrect, and thus few assumptions need to be revised.\n\nThe opposite on this spectrum might be something like Neovim, where each hour of\nnew development produces over five hours of maintenance over the lifetime of the\nproject. Neovim likely needs to adapt to a varied set of environments and\nworkflows, where all sorts of edge cases show up.\n\nIsn’t this *such* a useful rule of thumb already? Now the developers of e.g.\ntmux know that for every hour of new development they plan, they’ll have to\nbudget around 2.6 hours of maintenance. You can do this for your own\nprojects! Even if you haven’t fitted the curve to your project’s history (or you\ndon’t have a project history to fit to), it seems that 3 hours is somewhere in\nthe middle of the range, so you can assume three hours of maintenance per hour\nof new development.\n\nBut when should you plan to do that maintenance? That’s another thing we can\nquery of the geometric model.\n\n| Project | Elimination time |\n| --- | --- |\n| Syncthing | 2 years |\n| VSCode | 2 years |\n| nginx | 4 years |\n| React Native | 5 years |\n| Rust | 6 years |\n| Neovim | 7 years |\n| tmux | 8 years |\n| Go | 13 years |\n\nThe amount of maintenance needed from new development shrinks over time, as bugs\nin the code are ironed out. The *elimination time* in this table is the amount\nof time it takes until a hundred lines of new development effort need less than\none line of maintenance work per month.\n\nWe can tell that some projects get through their maintenance fairly quickly\n(Syncthing, VSCode), but for others it takes longer to find the bugs and sort\nthem out (tmux, Go). The average is six years.\n\nThis completes the planning guideline: if we start up a new project, for each\nhour of new development we plan, we should budget for three hours of maintenance\nspread out over six years, geometrically decaying. Here’s a handy table.\n\n| New development planned: | 1 day | 1 week | 1 month |\n| --- | --- | --- | --- |\n| Maintenance same year | 10 hours | 6 days | 26 days |\n| \"         year 2 | 7 hours | 4 days | 18 days |\n| \"         year 3 | 5 hours | 3 days | 13 days |\n| \"         year 4 | 3 hours | 2 days | 9 days |\n| \"         year 5 | 2 hours | 1 day | 6 days |\n| \"         year 6 | 2 hours | 1 day | 4 days |\n\nI’m actually surprised that in this average case, just the maintenance induced\n*in the same year* as the original new development exceeds the new development\ntime. Thus a one-week project is not a one-week project, it’s a two-week project\neven when it includes only maintenance performed in the same year. (It’s a\nfour-week project when considering all maintenance borne out of it.)\n\n# Further development\n\nWhile yes, I believe that table is better than nothing – and possibly better\nthan what many are doing today – the geometric model is not realistic. For\nexample, it says that one day of new development has the same elimination time\nas a month of new development. It also does not account for the size of the\nexisting code; I would think adding more features to an already-big code base\nshould produce more maintenance than adding features to a small code base.\n\nAnother thing that bugs me about the geometric model is that the amount of\ntotal maintenance produced by a unit of new development varies greatly across\nprojects, as does the elimination time. In order to use the geometric model\nfor planning, we should really fit those values for each project specifically,\nrather than use these rough averages. These averages happen to work great for\nprojects like Rust, VSCode. They are pessimistic for projects like Go,\nSyncthing, tmux, and nginx. And they still underestimate the maintenance\nrequired for a project like Neovim.\n\nI don’t think we’ll ever get a model of induced maintenance that is completely\nfree of estimation – some projects simply need more maintenance than others –\nbut perhaps we can get an slightly better fit? Perhaps we can find a model where\nsome parameters are stable across projects and don’t need re-estimation? That\nwould tell us something deeper about how software development works.\n\nI have some ideas for how to go about this, but that’ll be another day.\n\n# Acknowledgements\n\nI am grateful to James Shore for reviewing a draft of this article. He had very\ninsightful suggestions for improvements. In particular, some of the detailed\nsidenotes clarifying the methodology are entirely to his credit. As always,\nmistakes are my own.\n\nHe also noted that my presentation of his application of the threshold model was\nbased on a flawed reading of the spreadsheet. To clarify, I must emphasise that\nthe primitive application of the model we use here – where all new development\nadds an absolute level of maintenance – is not the model Shore presented, nor\nthe way he used it in his article.\n\nThe way Shore uses the model, he lets past new development drive both\nmaintenance and hypothetical new development, and we cannot do that, because we\nalready have the actual new development that happened. I would argue the\napplication in this article makes for a better test of general fit and validity,\nbut it says very little about the way Shore applies the model, which is in\ncompletely different circumstances.\n\nI strongly recommend reading his article series, and digging into the details of\nthe spreadsheet, if you’re curious about that.\n\n# Notes\n\n1. This article will assume that necessary maintenance gets performed,\n   and if maintenance is not performed, that’s because it wasn’t strictly\n   *necessary* from the aggregate users’ points of view. I know a lot of people\n   would object to that assumption because maintenance they think of as necessary\n   is not performed, but try to suspend your disbelief. If you keep using the\n   software even when that thing is not getting fixed, how necessary is that thing\n   *really* to keep you around as a user?\n2. In this analysis, I am counting the\n   gross commit size, i.e. additions plus deletions, as the amount of effort that\n   went into the commit. One can argue that this is a bad measurement of effort,\n   but it’s the best I have, and in my experience, on longer timescales like the\n   ones we look at here, it’s not so bad.\n3. Note that we\n   are not using the threshold model to predict the *fraction* of maintenance here,\n   but instead applying it primitively for what it says about the *absolute size*\n   of the maintenance demand. In Shore’s original application, he was able to\n   predict the fraction of maintenance through the threshold model, because the\n   model was allowed to also determine the rate of new development (through a fixed\n   monthly work rate.). We don’t do that, because we have the real new development\n   rate of the tmux project. It wouldn’t make sense to impose on the data an\n   assumed new development rate that we already know isn’t true.\n4. If new development had been reduced to\n   make room for the maintenance work, as Shore argues is the case for many\n   corporate projects, then maintenance would have leveled off as new development\n   grinds to a halt. But clearly, in the tmux case, new development does not reduce\n   *that much* to make room for maintenance work. And the same is true for all\n   projects I surveyed, including corporate-backed ones whose primary contributers\n   are on a payroll.\n5. Shore would argue that we cannot base\n   our judgment on a constant level of new feature development because new features\n   should slow down as maintenance takes over the total work effort. But in the\n   projects I’ve looked at, new development seems to happen at a relatively\n   constant level.\n6. The reason the geometric model starts at 5 % rather than\n   the 0.8/21.7=3.8 % the threshold model has is because the decay starts happening\n   immediately, and proceeds monthly through the first year. Thus, the total\n   maintenance the first year will still be 10 days in this geometric model. (Or\n   nearly so, 11 days is what you get with these rounded numbers.)\n7. That means after one year, the maintenance required\n   for 100 lines of work is shrunk to 3 lines of effort per month. After five\n   years, it’s down to half a line of effort per month. After ten years, it’s\n   barely noticeable, at a twentieth of a line per month.\n","body_html":"<p>James Shore posits that <a href=\"https://www.jamesshore.com/v2/blog/2026/you-need-ai-that-reduces-your-maintenance-costs\" rel=\"nofollow ugc noopener\">each person-month spent writing code results in 10 days\nof maintenance</a> in the first year, then 5 days every year after that. Naïvely\ninterpreted, this is a <em>threshold</em>-based model for induced maintenance, and its\ninteresting because it’s so simple.</p>\n<p>If it could be shown to be true, that’d be useful. The argument Shore is\nmaking about the effects of robot-generated code does not depend on the specific\nnumbers, so Shore’s numbers come from a hypothetical wisdom-of-the-crowds\naggregation rather than concrete data. But no hypotheticals are necessary here.\nWe have a thing called git.</p>\n<h1 id=\"testing-the-threshold-model-of-maintenance\">Testing the threshold model of maintenance</h1>\n<p>Let’s say <a href=\"https://entropicthoughts.com/cheaper-llm-labeling\" rel=\"nofollow ugc noopener\">we have a way of labeling each commit</a> as either “new development” or\n“maintenance”. Then we can count how many commits of each type there are in a\nmonth.[1] Possibly better, we can count <a href=\"https://entropicthoughts.com/lines-of-code\" rel=\"nofollow ugc noopener\">how much\ncomplexity has been handled</a> in a month.[2]</p>\n<p>The following plot shows the cumulative effort that has gone into the\ndevelopment of tmux since its beginning to the day I start writing this article.</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-01.svg\" alt=\"induced-maintenance-demand-01.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>We will look first at the black curve, which represents effort spent adding\nfeatures to tmux. From left to right:</p>\n<ul><li><p>In the first month of the repository, a few thousand lines of feature work are</p><p>present almost from the start.</p></li><li><p>From the start in 2008 to 2010, tmux saw rather intense activity at</p><p>around 30,000 lines of new development effort per year.</p></li><li><p>Then new development slowed down, and between 2010 and 2026, it happened at a</p><p>fairly steady pace of 8,000 lines of effort per year.</p></li><li><p>As of today, tmux stands at just over 230,000 lines of effort of new</p><p>development that have happened throughout its history.</p></li></ul>\n<p>To see how much effort has been spent on maintenance, we perform the same\nexercise but with the red curve instead.</p>\n<ul><li><p>Maintenance started dipping behind new development early on, but then traced</p><p>fairly closely to new development between 2008 and 2014.</p></li><li><p>After that, maintenance took off at a rate of 30,000 lines of effort per year,</p><p>continuing at that pace until 2022.</p></li><li>Then it slowed down again to around 10,000 lines of effort per year.</li><li>As of today, tmux has required around 430,000 lines of effort for maintenance.</li></ul>\n<p>In other words, of the total roughly 660,000 lines of effort spent on tmux, only\nabout a third has been on new development. This has changed over time, and we\ncan find roughly four regimes in the project’s history.</p>\n<ul><li>2008–2010: Total effort is 60,000 lines per year. About 50 % of that is maintenance.</li><li><p>2010–2014: Total effort is 16,000 lines per year. About 50 % of that is</p><p>maintenance.</p></li><li><p>2014–2022: Total effort is 38,000 lines per year. About 80 % of that is</p><p>maintenance.</p></li><li><p>2022–2026: Total effort is 18,000 lines per year. About 55 % of that is</p><p>maintenance.</p></li></ul>\n<p>This is not quite the continuous increase of maintenance fraction predicted by\nthe threshold model. To be sure, we should also check visually. The prediction\nof the threshold model is represented by the dotted red line.[3]</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-02.svg\" alt=\"induced-maintenance-demand-02.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>All the way from 2008 to 2022, the simple threshold model does actually fairly\nclosely predict the amount of maintenance tmux has required. But the exponential\nnature of the threshold model means its prediction eventually goes up faster\nthan actual maintenance performed.[4] This means the model fit will likely worsen as time goes on.</p>\n<p>The threshold model is also not a great fit for some other projects, where it\ngenerally overestimates the amount of maintenance performed. As one example,\nmaintenance work has made up 63 % of the effort spent on nginx to date, but the\nthreshold model suggests it should be 81 %. Other projects where the model\noverestimates the maintenance requirements are Rust, VSCode, and Go.</p>\n<p>In contrast, the model underestimates the amount of maintenance required for\nNeovim. The Neovim project has been maintenance-heavy from the start, and\nthrough its history, 83 % of the work on Neovim has been maintenance, but the\nthreshold model suggests it should be 70 %.</p>\n<p>However, the more general problem with the threshold model is one of timing. This is\nbest illustrated with Syncthing.</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-03.svg\" alt=\"induced-maintenance-demand-03.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>The threshold model lands close to the correct lifetime maintenance fraction\nhere (70 % vs. the real 67 %) but it is nowhere near following the actual maintenance\ncurve.</p>\n<p>An apologist could argue that the lack of curve-following is not because the\nmodel is wrong, but because the Syncthing project is an outlier that decided to\nfront-load a bunch of maintenance. Unfortunately, Syncthing isn’t the only\nproject where this happens, and it’s actually a symptom of the big flaw of the\nthreshold model. Given a constant level of new feature development, it predicts\nmaintenance will grow exponentially.[5] That doesn’t seem to be what happens in practise in the\nprojects I’ve looked at.</p>\n<h1 id=\"a-geometric-model\">A geometric model</h1>\n<p>But maybe we can rescue the model by refining it. The original threshold model\nsays that the 100 lines of effort I spend on new development today contributes\nat least 5 lines of maintenance effort per year until infinity. That’s probably\nnot true, in part because old code tends to be more stable, but also because\ncode is gradually rewritten, so the 100 lines I made today might not even be\naround five years from now.</p>\n<p>We can tweak the threshold model to account for this, by adopting a geometric\ndecay on the maintenance induced by new development. If we pick numbers\nconsistent with what Shore proposed, we’d say that maintenance starts at 5 % of\nthe work performed[6], and decays\nwith 3.6 % per month.[7] However, these numbers\nwould yield results very similar to what we’ve already seen: the maintenance\ncurve doesn’t track actual maintenance performed.</p>\n<p>However, we can pick other numbers. For example, if maintenance starts at 4 % of\nthe work performed, and decays with 2.6 % per month, we get a maintenance curve\nthat tracks fairly closely to the new development curve. This happens to work\nwell for nginx, which is light on maintenance:</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-04.svg\" alt=\"induced-maintenance-demand-04.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>For a project that needs more maintenance, like tmux, the same numbers don’t\nwork. They produce a curve that underestimates the maintenance required.</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-05.svg\" alt=\"induced-maintenance-demand-05.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>We can ask our computer to pick out the numbers that produce the\noptimally-fitting modified geometric curve for tmux. This happens at the same 4 %\ninitial value, but decaying with 1.4 % instead of 2.6 %. Here it is,\ngraphically:</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-06.svg\" alt=\"induced-maintenance-demand-06.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>If we continue to do this for all projects we have data for, we get a set of\nnumbers with large variation.</p>\n<div class=\"table-wrap\"><table><thead><tr><th>Project</th><th>Up-front maintenance</th><th>Decay</th></tr></thead><tbody><tr><td>nginx</td><td>4 %</td><td>2.6 %</td></tr><tr><td>tmux</td><td>4 %</td><td>1.4 %</td></tr><tr><td>Neovim</td><td>20 %</td><td>3.8 %</td></tr><tr><td>Syncthing</td><td>29 %</td><td>14 %</td></tr><tr><td>React Native</td><td>7 %</td><td>3.2 %</td></tr><tr><td>Go</td><td>3 %</td><td>0.7 %</td></tr><tr><td>VSCode</td><td>48 %</td><td>19 %</td></tr><tr><td>Rust</td><td>12 %</td><td>3.6 %</td></tr></tbody></table></div>\n<p>These numbers are not intended to tell us anything causal about how maintenance\ncomes to be. Rather, they’re the <em>just-so</em> numbers we are forced to pick to make\nthe geometric curve follow the actual maintenance performed closely, for each project.</p>\n<p>We can take these numbers and extend the maintenance curve ten years into the\nfuture, and predict how much maintenance will be needed in these projects even\nif they completely stop all new development. Here’s nginx.</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-07.svg\" alt=\"induced-maintenance-demand-07.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>The curve illustrates that nginx is already fairly close to their current\nmaintenance saturation point, and rather little maintenance remains if they\nfreeze all new development now. We can contrast this with something like tmux,\nwhich, when extended a decade forward, has a long way to go until their\nmaintenance curve plateaus.</p>\n<figure><img src=\"https://entropicthoughts.com/image/induced-maintenance-demand-08.svg\" alt=\"induced-maintenance-demand-08.svg\" loading=\"lazy\" decoding=\"async\" referrerpolicy=\"no-referrer\" /></figure>\n<p>Although it’s neat to be able to reproduce maintenance curves for projects, we\nshouldn’t really project these curves into the future because that gives viewers\nthe idea that the curves are predictive, when in reality they should be thought\nof as descriptive. But! These plots indicate that maybe there’s a more\nhuman-friendly way to present the numbers, that say something more intuitive\nabout the projects.</p>\n<h1 id=\"the-geometric-model-to-characterise-projects\">The geometric model to characterise projects</h1>\n<p>Here’s one way to interpret the numbers of the geometric model. With a\ngeometrically decaying series, the sum of all numbers is computed by dividing\nthe starting value by the decay factor. The sum, in this case, represents the\ntotal amount of maintenance performed relative to the new development effort.</p>\n<div class=\"table-wrap\"><table><thead><tr><th>Project</th><th>Total maintenance</th></tr></thead><tbody><tr><td>nginx</td><td>1.5×</td></tr><tr><td>Syncthing</td><td>2.0×</td></tr><tr><td>React Native</td><td>2.1×</td></tr><tr><td>VSCode</td><td>2.5×</td></tr><tr><td>tmux</td><td>2.6×</td></tr><tr><td>Rust</td><td>3.2×</td></tr><tr><td>Go</td><td>4.3×</td></tr><tr><td>Neovim</td><td>5.3×</td></tr></tbody></table></div>\n<p>This is <em>so interesting</em>. According to the geometric model, each hour of\nnew development on nginx produces 1.5 more hours of maintenance work over the\nlifetime of the project. That is the lowest figure of these projects. It could\nmean that</p>\n<ul><li><p>The nginx developers only accept high-quality code, since it needs so little</p><p>maintenance going forward, or</p></li><li><p>nginx runs in fairly predictable environments where few assumptions can be</p><p>incorrect, and thus few assumptions need to be revised.</p></li></ul>\n<p>The opposite on this spectrum might be something like Neovim, where each hour of\nnew development produces over five hours of maintenance over the lifetime of the\nproject. Neovim likely needs to adapt to a varied set of environments and\nworkflows, where all sorts of edge cases show up.</p>\n<p>Isn’t this <em>such</em> a useful rule of thumb already? Now the developers of e.g.\ntmux know that for every hour of new development they plan, they’ll have to\nbudget around 2.6 hours of maintenance. You can do this for your own\nprojects! Even if you haven’t fitted the curve to your project’s history (or you\ndon’t have a project history to fit to), it seems that 3 hours is somewhere in\nthe middle of the range, so you can assume three hours of maintenance per hour\nof new development.</p>\n<p>But when should you plan to do that maintenance? That’s another thing we can\nquery of the geometric model.</p>\n<div class=\"table-wrap\"><table><thead><tr><th>Project</th><th>Elimination time</th></tr></thead><tbody><tr><td>Syncthing</td><td>2 years</td></tr><tr><td>VSCode</td><td>2 years</td></tr><tr><td>nginx</td><td>4 years</td></tr><tr><td>React Native</td><td>5 years</td></tr><tr><td>Rust</td><td>6 years</td></tr><tr><td>Neovim</td><td>7 years</td></tr><tr><td>tmux</td><td>8 years</td></tr><tr><td>Go</td><td>13 years</td></tr></tbody></table></div>\n<p>The amount of maintenance needed from new development shrinks over time, as bugs\nin the code are ironed out. The <em>elimination time</em> in this table is the amount\nof time it takes until a hundred lines of new development effort need less than\none line of maintenance work per month.</p>\n<p>We can tell that some projects get through their maintenance fairly quickly\n(Syncthing, VSCode), but for others it takes longer to find the bugs and sort\nthem out (tmux, Go). The average is six years.</p>\n<p>This completes the planning guideline: if we start up a new project, for each\nhour of new development we plan, we should budget for three hours of maintenance\nspread out over six years, geometrically decaying. Here’s a handy table.</p>\n<div class=\"table-wrap\"><table><thead><tr><th>New development planned:</th><th>1 day</th><th>1 week</th><th>1 month</th></tr></thead><tbody><tr><td>Maintenance same year</td><td>10 hours</td><td>6 days</td><td>26 days</td></tr><tr><td>&quot;         year 2</td><td>7 hours</td><td>4 days</td><td>18 days</td></tr><tr><td>&quot;         year 3</td><td>5 hours</td><td>3 days</td><td>13 days</td></tr><tr><td>&quot;         year 4</td><td>3 hours</td><td>2 days</td><td>9 days</td></tr><tr><td>&quot;         year 5</td><td>2 hours</td><td>1 day</td><td>6 days</td></tr><tr><td>&quot;         year 6</td><td>2 hours</td><td>1 day</td><td>4 days</td></tr></tbody></table></div>\n<p>I’m actually surprised that in this average case, just the maintenance induced\n<em>in the same year</em> as the original new development exceeds the new development\ntime. Thus a one-week project is not a one-week project, it’s a two-week project\neven when it includes only maintenance performed in the same year. (It’s a\nfour-week project when considering all maintenance borne out of it.)</p>\n<h1 id=\"further-development\">Further development</h1>\n<p>While yes, I believe that table is better than nothing – and possibly better\nthan what many are doing today – the geometric model is not realistic. For\nexample, it says that one day of new development has the same elimination time\nas a month of new development. It also does not account for the size of the\nexisting code; I would think adding more features to an already-big code base\nshould produce more maintenance than adding features to a small code base.</p>\n<p>Another thing that bugs me about the geometric model is that the amount of\ntotal maintenance produced by a unit of new development varies greatly across\nprojects, as does the elimination time. In order to use the geometric model\nfor planning, we should really fit those values for each project specifically,\nrather than use these rough averages. These averages happen to work great for\nprojects like Rust, VSCode. They are pessimistic for projects like Go,\nSyncthing, tmux, and nginx. And they still underestimate the maintenance\nrequired for a project like Neovim.</p>\n<p>I don’t think we’ll ever get a model of induced maintenance that is completely\nfree of estimation – some projects simply need more maintenance than others –\nbut perhaps we can get an slightly better fit? Perhaps we can find a model where\nsome parameters are stable across projects and don’t need re-estimation? That\nwould tell us something deeper about how software development works.</p>\n<p>I have some ideas for how to go about this, but that’ll be another day.</p>\n<h1 id=\"acknowledgements\">Acknowledgements</h1>\n<p>I am grateful to James Shore for reviewing a draft of this article. He had very\ninsightful suggestions for improvements. In particular, some of the detailed\nsidenotes clarifying the methodology are entirely to his credit. As always,\nmistakes are my own.</p>\n<p>He also noted that my presentation of his application of the threshold model was\nbased on a flawed reading of the spreadsheet. To clarify, I must emphasise that\nthe primitive application of the model we use here – where all new development\nadds an absolute level of maintenance – is not the model Shore presented, nor\nthe way he used it in his article.</p>\n<p>The way Shore uses the model, he lets past new development drive both\nmaintenance and hypothetical new development, and we cannot do that, because we\nalready have the actual new development that happened. I would argue the\napplication in this article makes for a better test of general fit and validity,\nbut it says very little about the way Shore applies the model, which is in\ncompletely different circumstances.</p>\n<p>I strongly recommend reading his article series, and digging into the details of\nthe spreadsheet, if you’re curious about that.</p>\n<h1 id=\"notes\">Notes</h1>\n<ol><li><p>This article will assume that necessary maintenance gets performed,</p><p> and if maintenance is not performed, that’s because it wasn’t strictly\n <em>necessary</em> from the aggregate users’ points of view. I know a lot of people\n would object to that assumption because maintenance they think of as necessary\n is not performed, but try to suspend your disbelief. If you keep using the\n software even when that thing is not getting fixed, how necessary is that thing\n <em>really</em> to keep you around as a user?</p></li><li><p>In this analysis, I am counting the</p><p> gross commit size, i.e. additions plus deletions, as the amount of effort that\n went into the commit. One can argue that this is a bad measurement of effort,\n but it’s the best I have, and in my experience, on longer timescales like the\n ones we look at here, it’s not so bad.</p></li><li><p>Note that we</p><p> are not using the threshold model to predict the <em>fraction</em> of maintenance here,\n but instead applying it primitively for what it says about the <em>absolute size</em>\n of the maintenance demand. In Shore’s original application, he was able to\n predict the fraction of maintenance through the threshold model, because the\n model was allowed to also determine the rate of new development (through a fixed\n monthly work rate.). We don’t do that, because we have the real new development\n rate of the tmux project. It wouldn’t make sense to impose on the data an\n assumed new development rate that we already know isn’t true.</p></li><li><p>If new development had been reduced to</p><p> make room for the maintenance work, as Shore argues is the case for many\n corporate projects, then maintenance would have leveled off as new development\n grinds to a halt. But clearly, in the tmux case, new development does not reduce\n <em>that much</em> to make room for maintenance work. And the same is true for all\n projects I surveyed, including corporate-backed ones whose primary contributers\n are on a payroll.</p></li><li><p>Shore would argue that we cannot base</p><p> our judgment on a constant level of new feature development because new features\n should slow down as maintenance takes over the total work effort. But in the\n projects I’ve looked at, new development seems to happen at a relatively\n constant level.</p></li><li><p>The reason the geometric model starts at 5 % rather than</p><p> the 0.8/21.7=3.8 % the threshold model has is because the decay starts happening\n immediately, and proceeds monthly through the first year. Thus, the total\n maintenance the first year will still be 10 days in this geometric model. (Or\n nearly so, 11 days is what you get with these rounded numbers.)</p></li><li><p>That means after one year, the maintenance required</p><p> for 100 lines of work is shrunk to 3 lines of effort per month. After five\n years, it’s down to half a line of effort per month. After ten years, it’s\n barely noticeable, at a twentieth of a line per month.</p></li></ol>","headings":[{"level":1,"text":"Testing the threshold model of maintenance","id":"testing-the-threshold-model-of-maintenance"},{"level":1,"text":"A geometric model","id":"a-geometric-model"},{"level":1,"text":"The geometric model to characterise projects","id":"the-geometric-model-to-characterise-projects"},{"level":1,"text":"Further development","id":"further-development"},{"level":1,"text":"Acknowledgements","id":"acknowledgements"},{"level":1,"text":"Notes","id":"notes"}]}}