What a maintenance retainer actually covers month to month
A client's logistics dashboard went live on a Tuesday. By Friday the following week, we had the first maintenance request: an Excel export was truncating addresses at 30 characters because a column width had been hardcoded. That is what the first month of a maintenance arrangement looks like — small, specific things that were not visible until real users hit them.
We sell maintenance as a monthly retainer, not as an open-ended promise. The retainer buys a fixed number of hours — usually 10 to 20, depending on application complexity — and those hours cover four categories of work.
The first is monitoring and uptime. We keep CloudWatch alarms on the services we built, and when an alarm fires at 2:14 AM because a queue backlog crossed a threshold, one of us picks it up. This is not a dedicated NOC. It is three people who know the system and have PagerDuty on their phones. If the alarm is a false positive, we adjust the threshold and note it in the monthly report. If the database is actually down, we are on a call with AWS support within fifteen minutes.
The second is bug fixes. A bug is behavior that contradicts the documented spec or breaks a previously working flow. The address truncation above is a bug. A user asking for a third filter column on the orders table is not — that is a change.
The third is dependency and infrastructure updates. Once a month, we pull the latest patch versions of libraries in the dependency tree, run the test suite, and ship if everything passes. We do not jump minor versions without a separate conversation. When AWS deprecated a Lambda runtime last quarter, the migration to Node 20 was covered under maintenance because it was a forced, bounded change. Moving from REST to GraphQL would not be.
The fourth is small changes — and this is where most of the negotiation happens. We define "small" as something one person can complete and test within two hours. Renaming a status label, adding a required field to a form, changing a hardcoded tax rate before the new financial year. These accumulate, and we track them against the monthly hour budget. When the budget is exhausted, further requests queue for the next cycle or move to a separate statement of work.
What maintenance does not cover: new features, schema redesigns, third-party integrations, performance optimization campaigns, or anything requiring a design round. A client once asked us to "just maintain" a new payment gateway integration under the existing retainer. The integration itself took eleven hours across two people, plus three hours of testing against staging. We scoped it as a separate piece of work and billed it accordingly. The maintenance retainer then covered the post-launch fixes — a webhook retry logic gap and a currency rounding mismatch.
The monthly report we send is one page. It lists what broke, what we fixed, what updates shipped, and how many hours remain. If a client used 4 of 10 hours in a month, those hours do not roll over. The retainer is for availability and attention, not for a bank of hours that compounds. We explain this before signing, because it is the one thing people push back on.
Some months are quiet. The dashboard runs, alarms stay green, the only work is the routine dependency bump and a report saying nothing happened. That is a good month. It means the system is stable and the original build held up. A maintenance arrangement that is constantly busy with fixes is usually a sign that the launch was rushed, not that the retainer is good value.
We stay on after launch because the first three months of production use surface things no amount of staging can. The retainer is the structure that makes that possible without either side guessing what they owe each other.