In this guide 6 sections
Six things move a maintenance quote: framework age, code size and documentation, hosting and integrations, incident volume, response hours and upgrade backlog. Compare vendors on those six rows, not on the headline monthly figure, and ask each one to write down what it assumed about your system. Assumptions explain gaps.
The age of the stack sets the baseline
An application on a framework its maintainers still patch is cheap to keep alive, because security fixes arrive from upstream with every minor release. A retired Laravel or Symfony release is not. Every fix needs a workaround, each Composer or npm library stays pinned to an old version, and a developer must test every pinned package by hand before touching anything. Hours add up.
Ask the vendor to read your composer.json, package.json or requirements.txt before quoting, and to list what it finds in the quote itself. Those files show how many packages are outdated and which ones no longer receive security fixes from their maintainers, which is the first thing a careful vendor checks.
A quote without that look is a guess. Guesses get padded, and padding costs you.
- Framework and language versions in use
- Packages with no release for several years
- Database engine and its support dates
- Mobile builds pinned to an old SDK
Code size and documentation decide how long each fix takes
A developer who must read two hundred undocumented files before changing one line is billing you for the reading, and the reading repeats on every ticket. Documentation cuts that bill. A repository with a README, an ER diagram of the MySQL schema, a deployment note and a list of scheduled jobs removes most of that reading.
Test coverage matters a great deal. Without PHPUnit or Jest suites, each fix needs a manual regression pass across invoices, logins, role permissions, exports and the nightly import, and a tester repeats it every time. With them, the same check runs in minutes.
If documentation is missing, a good vendor will propose writing it in the first month, before any fix beyond the urgent ones is touched. Treat it as a one-time cost. It lowers every later invoice. Pay it early.
Hosting and integrations add hidden work
A single virtual server with a nightly database dump is simple to look after, because there are only two things that can break: the server and the dump. A setup with a load balancer, a queue worker, a Redis cache and three payment or courier APIs has more parts that can fail.
Each integration binds you to someone else’s software. When the courier changes its API, your code breaks even though you changed nothing, and the parcel labels stop printing on a Monday morning. Someone must watch for changes like that. Ask who.
List every outside service the application calls, with the account holder and the renewal date for each, in one table the vendor can read. Vendors price what they can see. Show them all of it.
- Servers, containers and managed databases
- SSL certificates and DNS renewals
- Payment gateway, SMS and email providers
- Backup jobs and who checks them
- Cron jobs and queue workers
Incident volume and response hours shape the retainer
Past tickets forecast future ones. Count the faults raised in the last twelve months, split by severity and by the module that failed, so the quote reflects real trouble spots. An application that fails weekly needs more reserved hours than one that fails twice a year, and the retainer should say so plainly.
Response time is priced separately. A reply within the working day costs less than a developer on call at night and on weekends, because someone must stay free to answer. Decide which screens genuinely stop the business when they fail, such as billing, dispatch or the gate pass printout, and ask for fast cover only on those.
Some vendors bill a fixed monthly retainer, others bill hours against a prepaid bank of time, and a few mix the two for urgent work. Neither model is better. What matters is that carried-over hours, overruns, out-of-hours rates and the notice period for ending the contract are written into the agreement before the first invoice.
Upgrade backlog is the part most quotes leave out
Routine upkeep holds the application where it is. Upgrade work moves it forward. Many quotes cover only upkeep, and the upgrade arrives months later as a surprise project with its own budget fight and its own delay.
Ask for the backlog to be listed as a separate line: framework upgrade, PHP or Node version move, replaced libraries, security patching. Each gets an estimate and a date.
Then lay the quotes side by side in one table with the same rows, so that a vendor who skipped hosting or documentation shows an empty cell. Blanks show you the gap. Send that table back and ask each vendor to fill it in, and treat a refusal to fill a row as an answer about what the vendor will cover.
Maintenance quote comparison sheet
One sheet, one column per vendor. Eight rows: stack review done, documentation work, hosting and integrations covered, monthly hours, response time by severity, incident history assumed, upgrade backlog items with dates, and exclusions. A last row lists what each vendor needs.
Open a blank worksheet to printQuestions owners ask
Why do two vendors quote very different amounts for the same application?
Usually they assumed different things. One counted only bug fixes with a next-day reply, while the other included security patching, monitoring, hosting checks and an upgrade plan. Put both quotes into the same row-by-row sheet, and the gap explains itself because each missing item shows up as an empty cell.
Does a bigger application always cost more to maintain?
Not always. A large application with tests, a clear structure and a recent framework can be cheaper to keep than a small, tangled one. Condition counts for more than size.
Should I ask for a code audit before getting a maintenance quote?
Yes, if the code is unread. A short audit gives every vendor the same facts and stops them padding the quote for unknowns, and you keep the report whichever vendor you choose.
