If you run a service business—agency, consulting, freelance—you invoice three ways at once: a standing retainer for your core hours, project fees for one-off work, and hourly overages when clients push past the retainer cap. One invoice, three billing modes. Most platforms break here. They can handle retainers. They can handle projects. They choke when you need all three on the same invoice, with the retainer offset against your hourly time so you don't double-bill. We tested Xero, FreshBooks, Zoho, and Wave on the same scenario: $5,000/month retainer for 160 hours, a $500 website tweak, and 15 hours of hourly work at $150/hour. The math is simple: the retainer covers the 15 hours, so the invoice should show the retainer + project fee, with $0 for hourly (because time is already prepaid). Few platforms get there without a spreadsheet and manual line-item editing. The problem: retainer offset logic When retainers exist, the invoicing platform must understand that pre-paid hours reduce billable hours . If a client has a $5K retainer covering 160 hours per month, and you log 15 hours in the month, that 15 hours is already paid—no hourly line item. The invoice should show: Retainer: $5,000 (services rendered within the cap) Project: $500 (outside the retainer scope) Hourly overages: $0 (all time covered by retainer) If the platform doesn't automate this offset, you face two bad choices: invoice for the retainer and project only (leaving billable hours off the invoice and in a limbo spreadsheet), or manually calculate overages and delete retainer lines, risking reconciliation chaos later. The issue compounds when your month has mixed activity: some hours logged to retainer, some to specific projects, and some to overages. Without smart offset logic, you end up hand-crafting every invoice, or worse, double-billing because the system invoiced both the retainer and the hourly time. Xero: strong retainer engine, weak offset logic Xero handles retainers cleanly through its repeating invoices feature. You can set a monthly retainer, link it to a service item, and it auto-generates every cycle. The interface is intuitive and the billing history stacks correctly. But offset breaks down. Xero does not automatically deduct logged time from a retainer on the invoice itself. If you log 15 hours against a retainer line in your time-tracking integration (via a third-party connector like Hubdoc or QuickBooks Time), Xero will still generate a full retainer invoice—and if you separately invoice hourly time, you've double-billed. The workaround: you must manually adjust the retainer invoice each month, subtracting the hourly time-value before sending. This works for one or two clients but scales poorly. By 20 clients on mixed billing, you're spending 2–3 hours per billing cycle on manual math. Verdict on Xero: Good for retainers alone; requires spreadsheet logic for mixed billing. FreshBooks: project-first thinking, incomplete retainer model FreshBooks excels at project invoicing. You can set project budgets, track time against them, and the platform will alert you when you're approaching budget cap. The UI is modern and the invoice templates are flexible. But FreshBooks treats retainers as a line item , not a billing mode . You add a retainer as a flat-fee line on an invoice, but there's no link between that retainer and your actual time logs. If you log time to a project, FreshBooks doesn't know that the time is covered by the retainer—it will happily invoice both the retainer line and the hourly task. You must manually set the retainer line to zero (or delete it) on months when you have heavy hourly time, and that adjustment lives only on the invoice—your dashboard still shows the retainer as unbilled, creating a false picture of outstanding revenue. Verdict on FreshBooks: Excellent for pure projects; retainers feel bolted on. Mixed billing requires frequent invoice edits. Zoho Books: offset logic exists, but it's half-hidden Zoho Books has the closest thing to real mixed-billing support. Its retainer management module allows you to set a retainer amount, attach it to service items, and define a usage limit in billable hours. When you log time against retainer-linked items, Zoho tracks consumed retainer hours separately. The offset logic is there: if your retainer is $5,000 for 160 hours and you log 15 hours, Zoho knows that 145 hours remain. On the invoice, Zoho can show the retainer + any hourly overages above the 160-hour cap, in theory skipping the redundant hourly line. The catch: this only works if you've linked your time-tracking system to Zoho (via a native integration like Zoho Projects or an external connector). If your team logs time in Asana, Clockify, or even just Zoho's own Projects module without tight billing sync, the retainer-offset logic breaks. You'll still get invoices that show both the retainer and hourly time, requiring manual reconciliation. Additionally, the retainer module is tucked in a submenu and