Pricing customer-hosted deployments without losing margin
Pricing customer-hosted deployments gets messy when support, upgrades, and incidents pile up. Use a simple model to scope work and keep margin.

Why these deals lose money
The license line looks clean on a quote. The work behind it does not.
Teams often price customer-hosted deployments like product sales. They charge for the software, maybe add a little setup time, and move on. The problem starts as soon as the customer installs it. Your team now deals with questions, release planning, environment issues, and support work that nobody priced properly.
A customer-hosted deal does not behave like a normal SaaS account. You do not control the server, network, backup rules, or update window. That means your team spends time on work the customer sees as "part of the deal," even when the quote never named it.
The first trap is simple. The license fee hides service work. A customer buys access to the product, but they also expect help with setup, environment checks, deployment questions, and post-launch fixes. None of this looks huge on day one. Over a quarter, it adds up fast.
Small support requests do the same damage. One email about logs. One call after a failed restart. One question about a reverse proxy rule. Each request feels minor, so the team answers it for free. Ten quick requests in a month can wipe out more margin than the original deployment work.
Variation makes it worse. Every customer runs a different setup, and every difference creates more support time. One team uses old Linux packages. Another has strict VPN access. A third puts your app behind custom SSO and firewall rules. Your product stays the same, but the work around it changes every time.
This is why self-hosted software pricing breaks when teams copy cloud pricing. In your own environment, you fix one setup. In customer-hosted work, you support many versions of many setups.
The biggest losses often come from one bad incident. A failed upgrade, disk issue, certificate problem, or outage during a customer release window can erase months of profit from the account. The customer does not care that the root cause sits in their stack. They still expect your team to join the call, investigate, and help restore service.
The pattern is easy to miss until you do the math. You sell a deployment with a healthy-looking margin. Then your engineers spend six extra hours on install friction, four on support tickets, and twelve on one weekend incident. The deal still brought in revenue, but the profit is gone.
Release overhead you need to count
A release that takes 20 minutes in your own setup can eat half a day on a customer's server. The code may already work, but the release still needs packaging, explanation, scheduling, and cleanup when something breaks.
This is where teams usually underquote. They price the feature and forget the work around the release. That work returns every time you ship, and it often lands on your most expensive people.
Count the tasks that repeat on every customer environment:
- preparing the release in a form the customer can use, whether that means a Docker image, versioned package, release notes, or install steps
- answering review questions from the customer's ops, security, or compliance team
- joining deployment calls, waiting for maintenance windows, and sitting through approvals
- checking logs, comparing config, and fixing install failures when their environment behaves differently from your test setup
A small update shows how quickly this grows. You ship a minor release on Tuesday. The build itself takes 30 minutes. Then the customer asks for a checksum, rollback notes, and a list of changed ports. Their change board meets the next morning, so your engineer joins a call and waits 40 minutes for approval. During install, the service fails because one environment variable still uses an old name. Now someone from your team is reading logs, checking config, and rerunning the deployment. A tiny update just turned into four or five hours.
What to include in your estimate
If releases happen often, do not hide them inside a vague support buffer. Give release overhead its own line item or bake a fixed number of hours into each deployment cycle. That makes the quote much easier to defend when a customer asks why a self-hosted deal costs more than a SaaS subscription.
A simple rule works well: if your team must touch the release, answer questions, join the call, or inspect a failed install, count it. If you skip that math, margin disappears one approval meeting at a time.
Diagnostics work that fills the week
Diagnostics looks small in a quote. In customer-hosted work, it rarely stays small.
You usually cannot log in, inspect the server, or restart anything yourself, so every question turns into a message, a wait, and another round of testing. The delay often costs more than the bug. A 20-minute check can stretch across two days when the customer sends partial details, uses the wrong build number, or forgets to mention a proxy, firewall rule, or local policy that changes how the app behaves.
Ask for the same set of details every time. If you handle this ad hoc, people miss half of what you need and your team burns hours guessing. At minimum, ask for the exact version and build, logs from the time of failure, the full error text or screenshots, the steps they took before the issue appeared, and basic environment notes such as OS, database version, reverse proxy, and recent changes.
You also need time to separate product bugs from local setup problems. That split matters because the work, owner, and urgency are different. If the app fails in every environment, your team owns the fix. If it works in a clean install but breaks behind the customer's custom proxy or old package version, your team still spends time proving that.
A common example is file uploads failing after launch. Your team tests the same build and cannot reproduce it. After two rounds of questions, you find that the customer's proxy blocks larger request bodies. That is not a product bug, but your team still spent hours collecting logs, replaying requests, and writing a clear explanation.
That last part needs a line item too. Do not stop at diagnosis. Write the next steps in plain language so the customer team can act without another meeting. Good notes should say who does what, what to change, how to verify the fix, and when your team needs to retest. That documentation is part of support cost estimation, not free cleanup.
Upgrade work after launch
Many teams price the initial install and forget what happens three months later. A customer skips two releases, wants new features, and expects a smooth upgrade in their own environment. That work is real, and it eats margin fast.
One common mistake is assuming every customer stays close to the current version. They do not. Some delay upgrades because of internal approvals, change freezes, or plain neglect. When that happens, your team pays the price through extra testing and longer troubleshooting.
Each upgrade needs more than a release package. You need to check how the new version behaves against older versions that customers still run. If you support several old releases, the test matrix grows fast. Version 3.8 might upgrade cleanly from 3.7, but fail from 3.4 because an old config file or background job still exists there.
Schema changes add another layer. If a release touches the database, someone needs to verify migration order, data integrity, and recovery time. Even a small column change can turn messy when the customer has custom reports, large tables, or stale data. Price time for pre-upgrade checks, the migration itself, and post-upgrade validation.
Rollback work matters too. Before each change, decide exactly how the team can undo it if the release goes wrong. That plan usually includes:
- a backup point and restore test
- the app version to roll back to
- database rules for reversal or repair
- a short smoke test after rollback
Without that prep, a failed upgrade becomes an open-ended incident.
A simple example makes the cost obvious. A customer runs a release from six months ago and asks for the latest build. Your team now needs to test the direct jump, confirm every intermediate schema change still works, review data quality, schedule downtime, and keep rollback steps ready. That can take half a day or two full days, depending on the stack.
Set the support window
You also need a clear rule for how long you support old releases. If you say nothing, customers assume you support everything forever. That gets expensive quickly.
Pick a window and put it in the quote and contract. For example, you might include upgrade support for the current release and the previous two minor versions. Anything older becomes a paid catch-up project. One rule like this keeps upgrade pricing sane and stops arguments later.
If your team cannot name the supported versions, the rollback method, and the migration checks before the deal closes, the quote is probably too low.
Incident ownership needs a price
Customer-hosted deployments start losing money when an outage happens and nobody agreed who reacts first. A vague line like "production support included" sounds harmless in a quote. At 11:40 p.m., it turns into phone calls, log review, and a long email thread that nobody planned to bill.
Start with a basic question: who watches alerts first? In most self-hosted setups, the customer should do that because they control the servers, network, VPN, DNS, and access. If you want your team to monitor production first, charge for on-call coverage every month. Quiet weeks do not make that work free. Someone still has to stay available.
Put a boundary around incident response
Response times need two versions: business hours and nights or weekends. A one-hour reply during the workday is one service level. A 15-minute reply at 2 a.m. is another, and it should cost more. If the quote does not separate them, customers often assume both are included.
You also need to split triage from fix work. Triage means confirming the problem, checking logs, finding where it started, and deciding who should act next. That may take 20 minutes, or it may take two hours. The full fix is separate. It can involve a patch, a rollback, a database repair, or coordination with another vendor. If you bundle all of that into "support," your margin disappears fast.
Ownership matters just as much. If their ISP drops traffic, their cloud account hits a quota, their email provider rejects messages, or their internal firewall blocks a port, that is not your incident to own. You can help diagnose it, but the customer should own the vendor calls and local changes unless the contract says otherwise.
A good quote should name five things clearly:
- who receives alerts first
- response times for work hours and after hours
- what triage includes
- which failures stay with the customer
- emergency rates and minimum billable time
Emergency work outside the plan needs its own rate card. Night and weekend work should have a higher hourly rate and a minimum charge. Even a short incident can burn half a day once context switching, testing, and follow-up are done.
A simple pricing method
Start with a 12-month view, not a launch quote. The easiest mistake is charging for setup and hoping support stays light. It rarely does.
Build your price from the events you expect over a year. Count every release, planned upgrade, support case, incident review, and customer call that will pull time from your team. If the customer runs the software in their own environment, assume more variation and more back-and-forth than a normal SaaS account.
A practical method looks like this:
- List the events you expect in a year. Include releases, upgrades, environment checks, support tickets, and at least a few urgent incidents.
- Estimate hours for each event. Count prep, meetings, diagnostics, fixes, testing, documentation, and follow-up.
- Multiply those hours by your real loaded hourly cost. Use the full cost of the people involved, plus tools and management time, not just salary.
- Add an incident pool. Rare bad weeks can eat a month of profit, so reserve hours for the messy cases you cannot predict exactly.
- Add your margin, then round the result to a clean number that is easy to approve and renew.
The math can stay simple:
Annual price = planned work + incident pool + margin
Planned work = sum of expected events x hours per event x loaded hourly cost
Loaded hourly cost matters more than most teams admit. If an engineer costs $70 per hour on paper, the real number may be much higher once you add payroll taxes, benefits, support tools, review time, and the cost of context switching.
The incident pool is your shock absorber. If one customer outage usually pulls in an engineer, a team lead, and two calls with the client, price that pain before it happens. Even a small reserve can keep one rough week from wrecking the deal.
Round the final number into a clean offer, such as a monthly support fee plus a release allowance. Clean pricing is easier to explain, and it gives you room to absorb normal variation without renegotiating every small task.
A simple example
Take a vendor with four customer-hosted installs. On paper, that can look easy to price. The team knows the product, each client runs the same core version, and nobody expects daily hand-holding. The numbers still get ugly if you price it as one flat yearly fee.
Assume each client gets six releases and two planned upgrades a year. If every release takes about 4 hours to package, coordinate, deploy, and verify, that is 96 hours a year across four clients. If each planned upgrade takes 8 hours, that adds 64 more.
Now add the work people forget to count. Diagnostics takes 3 hours a month per client on average. That means log review, environment checks, strange config issues, and calls that end with "it works now, but we should watch it." Across four clients, that is 144 hours a year.
Before incidents, the vendor is already at 304 hours.
Then one after-hours incident lands on a Sunday night. Maybe a certificate expires, a proxy rule breaks, or a customer deploys a change that affects your app. Even if the fix takes 6 hours, the real cost is higher. You lose sleep, Monday gets pushed around, and someone still has to write follow-up notes and check the system again the next day. A single event like that can add 10 to 12 hours fast.
At a loaded internal cost of $120 an hour, 316 hours comes to $37,920 a year. That is about $9,480 per client, and that assumes only one serious after-hours issue.
A better quote splits the money into two parts. Charge a base fee for the hosted deployment itself and the planned release calendar. Then add a monthly support retainer that covers routine diagnostics, normal questions, and a defined amount of incident readiness.
This structure protects margin because the predictable work and the messy work are not mixed into one guess. If a client stays quiet, the retainer still covers availability. If a client gets noisy, you can point to the support terms instead of eating the cost.
Mistakes that hurt margin
The most common pricing mistake is copying your cloud price into a customer-hosted deal. That almost never works. Self-hosted deployments bring extra release work, slower debugging, more meetings with IT teams, and more upgrade friction. If the price stays the same, margin drops with every ticket.
Unlimited help over email or chat is another leak. It sounds harmless during the sale, but those small messages pile up fast. A customer asks for logs, then a call, then a follow-up after hours. Soon your team acts like an on-call desk without getting paid like one. Put limits on channels, response times, and what counts as support.
Old versions are expensive in a quiet way. When you support too many past releases, every issue starts with detective work. Your team checks which build the customer runs, which patch level they missed, and whether the bug still exists in the current version. A short support window is not rude. It keeps the product maintainable.
Teams also lose money when they accept every incident before they know the cause. If the customer's firewall blocks traffic, their disk fills up, or their internal DNS breaks, that is not your application bug. Joint triage is fair. Full ownership from minute one is not, especially when you cannot touch the whole stack.
Custom patches cause damage that lasts longer than the invoice suggests. One customer asks for a quick fix outside the normal release cycle. Then that patch has to be tested again, merged again, and explained again during the next upgrade. A few requests like this can split one product into several versions that behave differently.
If a quote includes cloud-level pricing for a self-hosted install, open-ended chat support, broad support for legacy versions, full incident ownership, or discounted one-off patches, it probably needs another pass. These are the deals that look fine on paper and wear the team down six months later.
Quick checks before you send a quote
Most bad quotes fail before the contract starts. Teams price the first install, then absorb a year of releases, support calls, and weekend fixes because nobody wrote the limits down.
A customer-hosted deal needs a short rules section inside the proposal. Vague promises usually cost more than a lower day rate. Clear limits are easier to defend later.
Before you send numbers, answer five points in plain language:
- Count the release work across the next 12 months. If you expect one monthly patch and one quarterly upgrade review, that is 16 planned touchpoints, not one deployment.
- State which versions you support. Say whether you cover only the current release, the current release plus one previous version, or another fixed range. Include OS or database assumptions if they affect support.
- Put a hard cap on included support time. "Up to 6 hours per month" is easy to price. "Reasonable support" turns into open-ended work.
- Set after-hours rates and approval rules before anyone has an outage. Write the hourly rate, the minimum charge, and the customer contact who can approve emergency work.
- Decide when your team stops and the customer team takes over. If their firewall blocks traffic, their disk fills up, or their admin changes a setting, say whether you advise, fix it, or stop after diagnosis.
These points look small on paper. They are often where the margin disappears.
A simple stress test helps. Read the quote and imagine a Friday night incident after the customer skips two upgrades. Can you tell who owns first response, who approves paid work, and which version your team will touch? If not, the quote is still too loose.
This is where a good technical lead or fractional CTO often earns the fee. The job is not to make the proposal longer. It is to make the boundaries hard to misunderstand.
What to do next
Start with the narrowest support promise you can defend in writing. That usually means a defined release process, a basic diagnostics window, planned upgrade help, and clear rules for incident ownership. You can always add more later. It is much harder to take scope back after a customer decides that "support" means unlimited help.
A simple first contract often protects margin better than an ambitious one. If the customer wants faster response times, deeper incident coverage, or hands-on upgrade work, price those as add-ons. That keeps the base offer easier to sell and stops the quiet support creep that eats margin.
Keep a time log from day one. Do not track support as one blurry bucket. Split it into the work that actually drives cost:
- release prep and rollout time
- diagnostics and environment troubleshooting
- upgrade planning and execution
- incident response and follow-up
After a few weeks, patterns usually show up. One customer may need almost no release help but burn hours in diagnostics because their setup changes every month. Another may stay quiet until upgrade time, then need a full day of work. Once you track the categories, pricing gets much less guessy.
Review the numbers after the first quarter, not after a year. Three months is usually enough to see whether your quote matched reality. If diagnostics took twice as long as expected, fix the pricing model before renewal. If incident work stayed low, you may be able to offer a cleaner package with better margins.
Be strict during that review. Ask simple questions. Which work was included? Which work slipped in "just this once"? Which requests should move into paid project work next time? That short check often saves more money than any spreadsheet.
If the model still feels fuzzy, it helps to get a second opinion before you lock in long-term support terms. Oleg Sotnikov at oleg.is does Fractional CTO and startup advisory work, including pricing, architecture, and support-boundary decisions for small and midsize teams. Problems like this are usually cheaper to fix early than after six months of underpriced support.
A quote is only the starting point. The part that matters is the feedback loop you build after launch.
Frequently Asked Questions
Why does self-hosted pricing fail when I copy my SaaS price?
Because the customer controls the server, network, backups, and update window. Your team still spends time on packaging releases, answering ops questions, chasing environment bugs, and joining incident calls. A cloud price rarely covers that extra labor.
What hidden work should I include in every release estimate?
Price the work around the code, not just the build. Include release packaging, notes the customer can follow, security or ops review questions, deployment calls, log checks, config fixes, and post-install verification. If your team touches any part of the rollout, count the hours.
How should I estimate the annual price for a customer-hosted deal?
Use a 12-month view. Estimate how many releases, upgrades, support cases, customer calls, and urgent incidents you expect, then multiply the hours by your loaded hourly cost. Add a small incident reserve and your margin, then turn it into a clean offer such as a monthly support fee plus planned release work.
What details should I collect before I troubleshoot a customer issue?
Ask for the exact version and build, logs from the failure window, the full error text or screenshots, the steps they took before it broke, and basic environment facts such as OS, database, proxy, and recent changes. A fixed intake saves hours because your team stops guessing.
How do I price upgrades when customers lag behind versions?
Treat upgrades as project work, not free cleanup. Price testing from older versions, database migration checks, downtime planning, post-upgrade validation, and a rollback plan before anyone starts. Put a support window in the contract so customers know how many older versions you will touch.
Who should own alerts and first response during an outage?
In most customer-hosted setups, the customer should receive alerts first because they control the servers, DNS, VPN, firewall, and access. Your team can triage the app and fix product issues, but the customer should own local vendor calls and infra changes unless the contract says otherwise.
Should I charge extra for nights and weekends?
Yes. A one-hour reply during work hours and a 15-minute reply at 2 a.m. are different services. Charge a higher hourly rate for nights and weekends, set a minimum billable block, and name who can approve emergency work.
Is unlimited email or chat support a bad idea?
Usually no. Small messages turn into log reviews, calls, follow-up notes, and after-hours interruptions. Put limits on channels, response times, and included hours so routine support stays routine.
What contract limits protect margin the most?
Clear boundaries save more margin than a cheap day rate. State which versions you support, how much support time the fee covers, who owns first response, what triage includes, and where your team stops if the problem sits in the customer's stack. If you leave those points vague, the customer will fill in the blanks.
When should I review the pricing model after launch?
Review the deal after the first quarter, not at renewal. Track release work, diagnostics, upgrades, and incidents as separate buckets so you can see what actually eats time. If one category runs hot, fix the pricing model before it turns into a year of underpaid work.