Fixed price sounds straightforward until you’re the one who has to name the number. Price it too low and you’re finishing the work for free by week three. Price it too high and someone else’s guess wins the job. We’ve been pricing freelance projects this way for more than nine years, across 525 delivered orders on Fiverr (4.9 from 335 reviews) and more on Freelancer.com (5.0 from 156), and the scoping process below is what came out of that. It doesn’t remove the pricing risk. It moves the arguments from the middle of the project to before the contract gets signed, which is a much better place for them to happen.
What the scope document leaves out
Most scope documents are a features list: login, dashboard, checkout. That part is necessary, but it rarely prevents a dispute. What prevents a dispute is the second list: the things a client will reasonably assume are bundled in, written down as excluded.
If someone asks for a login system, we write down that password reset is included, that Google or Microsoft sign-in is a separate line unless it’s named, and that account deletion is scoped on its own. If someone asks for a product catalog, we write down whether search means full text or just category filters, and whether importing an existing spreadsheet is part of the build or billed separately. On most fixed-price contracts we write, the excluded list ends up longer than the included one. That’s the point: it’s where the disagreements would have started.
## Included
- Email/password auth with password reset
- Product catalog with keyword search
- Stripe checkout, one currency
## Excluded
- Google or Microsoft sign-in
- Multi-currency pricing
- Import from the client's existing spreadsheet
- Admin analytics dashboard
A document like that takes twenty minutes to write and saves hours of “I assumed that was included” later. We send it back for a plain yes before any code gets written. If a project needs that kind of conversation before you commit to a number, tell us what you’re building.
Milestones mark deliverables, not dates
A fixed-price contract still needs to be broken into payments, and the easy way to do that is by calendar week. We avoid that, because a calendar milestone gets hit whether or not the underlying work is actually done. That either pressures us to call something finished when it isn’t, or pressures the client to pay for progress they can’t see.
Each milestone is tied to something the client can look at and accept instead: a login flow they can use, a checkout that takes a real test card, an admin panel showing real records instead of placeholders. Payment follows acceptance of that deliverable. Milestone boundaries also work as the natural point for scope changes. When a client wants to add something mid-project, it doesn’t get folded into the milestone already in progress. It gets priced and scheduled as its own piece of work, either in the next milestone or as a separate one.
The questions that catch complexity before code starts
The projects that go over budget are rarely the ones with a hard feature. They’re the ones with a dependency nobody named at the start. Before we price anything, we ask about the parts of a system that don’t show up in a feature list.
Who else touches this data, and on what schedule? A product catalog that syncs from a vendor feed, pushes to a storefront, and rebuilds a search index is three separate integrations with three separate failure modes. On FurnitureAxis, a multi-tenant retail platform we built on Next.js with Prisma and PostgreSQL, that question is why the vendor catalog sync, the Shopify push, and the Algolia reindex run as a scheduled C# service instead of living inside the main request cycle. A cron job hitting three external APIs needs its own retry and failure handling, and that’s a scoped piece of work on its own.
Does more than one kind of user need to log in, and from more than one surface? FurnitureAxis needed Google and Microsoft sign-in, two-factor authentication, and an Expo mobile companion app talking to the same backend as the web app. “Add login” and “add login that works the same way from a phone app and supports two providers of enterprise sign-in” describe different amounts of work, even when a client uses the same sentence for both.
What happens to the client’s existing data? If someone is migrating off a spreadsheet or a legacy system, the shape of that data determines a good part of the schema before a single screen gets designed. We ask for a sample export before pricing anything that touches existing records.
Who holds the accounts the project depends on? Stripe, the domain registrar, the hosting account. Knowing who has the login before launch avoids a stall on day one because nobody can find the credentials for the service the whole app depends on.
None of these are exotic questions. They just don’t show up when a client describes what they want in feature terms. A client describes the software they see; the syncs and permissions holding it together are usually invisible until something breaks.
Where fixed price still breaks
This process doesn’t remove all risk. A client can discover mid-project that the feature they scoped isn’t the feature they actually need, and that’s a legitimate reason to change the plan. What the process does is keep two different problems separate: work we estimated badly, which is on us, and work that was never in the document, which becomes its own milestone with its own price. Keeping those apart is most of what lets a fixed-price relationship survive contact with a real project.
The verdict
A scope document doesn’t make a project simpler. It makes the complexity visible before either side has spent money assuming it wasn’t there. If you’re pricing out a build and want a second pair of eyes on where the scope actually sits, tell us what you’re building at /services/ and we’ll ask the boring questions before you sign anything.