Software Maintenance Contracts: What a Fixed Monthly Update Cycle Should Include

#software maintenance retainer

Founder & Lead Developer

Expert in software development and legacy code optimization

LinkedIn

Most businesses that sign a software maintenance retainer never ask what the monthly fee actually buys them. They know they want someone to "keep the system updated," and they assume the contract covers that. In practice, a lot of retainers are vague on purpose, because vague is easier to sell and easier to under deliver on. If you are evaluating a software maintenance retainer, or wondering whether the one you already pay for is worth renewing, there is a short list of things it should spell out in writing. Here is what to look for.

What a fixed monthly update cycle actually covers

A software maintenance retainer is a standing agreement to keep a system current and working, usually billed monthly, rather than a one off project. That sounds simple, but "keep it current" can mean almost anything depending on who you ask. A weak contract says the provider will "perform regular maintenance." A useful one says what gets updated, on what schedule, and what happens when an update breaks something.

At minimum, a fixed monthly cycle should name the layers being maintained: the language runtime (PHP, Node, whatever the application runs on), the framework, third party packages, and the operating system or container image underneath all of it. Each of these moves at a different pace. PHP ships security releases on a predictable schedule. A framework like Symfony has its own long term support cadence. npm packages in a five year old frontend can have dozens of outdated dependencies with no clear order to update them in. A retainer that treats all of this as one undifferentiated "updates" line item is one that has not been thought through, and it usually shows up later as either nothing getting updated or everything getting updated at once in a way that breaks the application.

Update frequency should be a number, not a feeling

Ask for a specific cadence. Monthly dependency updates with a quarterly review of the full stack is a reasonable baseline for most business applications. Weekly is sometimes justified for something handling payment data or regulated information, where the cost of a known vulnerability sitting unpatched is higher than the cost of more frequent testing cycles. Whatever the number is, it should be written into the contract, not described as "ongoing" or "as needed." A provider who cannot commit to a number is telling you that updates happen when they get around to it, which in practice means after something breaks.

Testing has to happen before anything reaches production

This is the part most retainers skip, and it is the part that actually protects you. An update that is not tested is a bet, not a maintenance task. The contract should describe what gets tested before a change ships: automated test suites where they exist, a manual smoke test of core flows (login, checkout, whatever the business depends on) where they do not, and a staging environment that mirrors production closely enough that a passing test there means something. If the retainer does not mention a staging environment at all, ask where updates get tested before your customers see them. Sometimes the honest answer is that they do not, and updates go straight to production. That is the arrangement some businesses can live with for a low stakes internal tool. It is not one you want for anything customer facing.

A good retainer will also say what happens when a test fails. The default should be that the update gets held back and investigated, not pushed through on a deadline because the monthly cycle says it is update day.

Breaking changes need an owner before they happen

Composer updates in a legacy PHP project without a clear routine are one of the most common ways a maintenance cycle quietly turns into an emergency. A dependency bump can silently change a method signature, deprecate a function your code calls, or shift a default behavior just enough to corrupt data without throwing an error. The retainer should state who is responsible for catching this, how (automated tests, a changelog review, a diff of the dependency's breaking change notes), and what the response looks like when it happens anyway. "We will investigate" is not a plan. "We roll back within the hour and the fix is scheduled into the next cycle with a root cause note" is.

This is also where you want clarity on scope. Does the retainer cover fixing a breaking change the update itself introduced, or does that count as new billable work? Providers differ on this, and it should not be a surprise discovered mid incident.

Security patches get a different clock than everything else

Routine dependency bumps can wait for the monthly cycle. A disclosed vulnerability in something your application depends on cannot. The contract should separate these two categories explicitly and commit to a faster response time for the second one, typically within 24 to 72 hours of a critical CVE becoming public, depending on exposure. If your maintenance contract has no language distinguishing "security patch" from "routine update," you are relying on the provider's judgment about urgency, and that judgment is not written down anywhere you can hold them to.

This matters even more for software that nobody internally still understands well enough to evaluate risk themselves. A business running on PHP 8.1 or older, or anything approaching its own end of life date, needs a maintenance partner who tracks those dates on your behalf and tells you before support ends, not after. We have covered what unsupported PHP exposure actually looks like in practice, and the short version is that "it still runs" is not the same as "it is still safe to run."

Reporting should tell you something you can act on

A non-technical owner does not need a changelog full of package version numbers. What is useful is a short monthly summary: what was updated, what was tested, anything flagged as a risk, and anything that needs a decision from your side. If your current retainer sends a report and you could not tell from reading it whether anything important happened last month, the reporting is not doing its job. Ask for a format that fits on one page and leads with the thing you actually need to know, which is almost always "is anything broken or at risk, and does it need your sign off."

Response times belong in the contract, not in a verbal promise

How quickly does the provider respond when something goes wrong outside the normal cycle? This should have a number attached, split by severity. A site that is fully down might warrant a one hour response commitment. A cosmetic bug can reasonably wait until the next business day. If the contract only has one response time for every kind of issue, someone eventually gets stuck waiting behind a low priority ticket while something urgent sits unaddressed, or the provider burns their time budget on minor fixes and has nothing left when it actually matters.

What to ask before signing

Before signing a software maintenance retainer, ask for the update cadence in writing, ask what gets tested and where, ask who owns a breaking change when it happens, ask for the security patch response window separately from the routine one, ask what the monthly report looks like, and ask for response times by severity. A provider who can answer all six clearly and specifically is one who has actually run this process before. A provider who answers in generalities is asking you to trust a process they have not written down, which means it probably does not exist yet in any consistent form.

If you are weighing a retainer against the alternative of handling updates yourself or leaving them until something breaks, it helps to first know how exposed your current system actually is. A short codebase assessment before you commit to a monthly contract will tell you what you are actually paying someone to maintain, and whether the retainer you are being offered matches the real risk in your system rather than a generic package. For codebases carrying real technical debt, an ongoing code quality consulting engagement can also fold maintenance into a broader plan to pay that debt down, rather than just keeping the current state patched indefinitely.

If you want a second opinion on a maintenance contract you have been offered, or want to know what a fixed monthly cycle should cost for your specific stack, write to us at hello@wolf-tech.io or have a look at what we do at wolf-tech.io. We will tell you plainly whether what is on the table covers what it should.