Month 1: Acme Retainer — ₹40k, 8 posts, 2 site updates, Slack support. You invoice day 1 via Sheets, get paid day 5. Smooth.
Month 2: You ship 10 posts (extra 2 quick), do site revamp hero as update, forget invoice until day 12 — client cash flow tight, pay day 22. You worked 18 days unfunded.
Month 3: Client: Pause retainer, too much back-and-forth on scope. They didn't churn for price. They churned for drift — 8 vs 10 posts no boundary, update vs revamp no FK, invoice no rhythm. Recurring work became monthly re-negotiation.
Retainers don't fail on delivery. They fail on linked repetition.
Why Sheets / Notion / HubSpot Lose Retainers
One-off projects tolerate manual ops. Recurring amplifies every gap ×12:
- Sheets —
Retainer logtab withMonth | Client | Amount | Statusaspaid?textYES. NoinvoiceStatusEnum draft|sent|paid|overduesrc/lib/db/schema.ts:58, norecurringInterval monthly|quarterly|yearlysrc/lib/db/schema.ts:80, norecurringNextDatesrc/lib/db/schema.ts:81. You set Google Calendar reminderInvoice Acme 1st; snooze 3 days; nowdueDatesrc/lib/db/schema.ts:72is guess. - Notion —
Acme Retainerdatabase with8 poststext property. Tasks forPost 3live in Trello boardAcme Content— newAcmestring, noprojectIdsrc/lib/db/schema.ts:47, nototalTasks/doneTaskssrc/app/api/projects/route.ts:28linked to invoice. Client gets3 revisionpromise in Notion, you countrevisionsin head. - HubSpot — Holds
Deal Amount monthlybut nottasks todo|in-progress|donesrc/lib/db/schema.ts:42orvaultItems clientIdsrc/lib/db/schema.ts:133forInstagram loginyou need weekly. Deal recurring is CRM field, notinvoices items jsonbsrc/lib/db/schema.ts:74+cron daily clonesrc/app/api/cron/daily/route.ts:275autoinvoice. Billing stays manual. - Flat vault/email — Monthly
Can you resend login for Insta?becauseacme-socialflat list has 4acme-instaentries nosocial platform/handle vaultItemIdsrc/lib/db/schema.ts:213.
Result: retainer feels ₹40k for whatever Acme asks rather than ₹40k for 8 posts + 2 updates. Without linked recurringNextDate + portal visibility, client anxiety spikes at month end, churn follows. Manual recurring loses ₹20-40k/quarter to forgotten invoices alone.
Recurring work needs recurring ops — not better memory.
The Linked Retainer Graph: Project → Tasks → Recurring Invoice → Portal
In RunoSO tenant_${id} src/lib/db/tenant.ts:47, retainer is a graph, not a Sheet row:
clients(status active src/lib/db/schema.ts:5) 1—∞ projects(clientId fk, budget numeric advance numeric type:content|dev|other status active|completed src/lib/db/schema.ts:23, deadline)
1—∞ tasks(projectId fk, dueDate, status todo|in-progress|done)
1—∞ invoices(clientId, projectId nullable, amount numeric, items jsonb, recurringInterval none|monthly|quarterly|yearly src/lib/db/schema.ts:80, recurringNextDate src/lib/db/schema.ts:81, status draft|sent|paid|overdue)
1—∞ vaultItems(clientId, projectId) + assetsSocial(vaultItemId)
portalTokens(tenantId+clientId unique src/lib/db/schema-public.ts:169)Setup once, runs monthly:
- Create retainer project.
POST /api/projectssrc/app/api/projects/route.ts:145—Client: Acme Corp,Title: Acme — Growth Retainer Aug 2026,type:content,status:active,budget:40000,advance:0,deadline= month end. Typednumeric(12,2)feedsFinanceOverviewClientMRR withoutSUMIF. - Template tasks for scope.
8 × Post + 2 × Site update + 1 × ReportingastaskswithdueDateweekly slots. Client sees6/8 doneprogress onClientDetailPageClientsrc/app/(dashboard)/clients/[id]/page.tsx. Over-scopeQuick post 9is newtaskonly after change-order bump tobudget— not silent free. - Recurring invoice.
POST /api/invoicessrc/app/api/invoices/route.ts:84—clientId + projectId,items jsonb8 posts + 2 updates,invoiceNumber FY sequential GOS/25-26/001,issueDate,dueDate,recurringInterval:monthlyrecurringNextDate:2026-09-01src/lib/db/schema.ts:80. Dailycronsrc/app/api/cron/daily/route.ts:275+src/lib/utils/recurring.ts:5clones onrecurringNextDateand advances date — you wake todraft→sentclone +notifications type:recurring_generatedsrc/lib/db/schema-public.ts:195, not midnight manual. - Portal self-serve.
POST /api/clients/[id]/portalsrc/lib/db/schema-public.ts:169→portal/[token]shows invoice PDFsendInvoiceEmail portal linksrc/lib/emails/send.ts:347, payment terms, progresstotalTasks/doneTasks. Client re-downloads without pinging. - Vault linked.
vaultItems category:password|api-keysrc/lib/db/schema.ts:123linkedclientId+assetsSocial vaultItemId— 1-clickInstalogin vs flatacme-insta ??guess monthly.
Retainer now self-describes: project scope, task progress, auto-billing, portal truth.
The Retainer Operating Rhythm
- Monthly (day 1): Cron clones invoice
draft→sent+sendReminderDigestEmailsrc/lib/emails/send.ts:469. You checkFinance receivablessrc/app/api/sidebar/stats/route.ts:55—pendingInvoicesbudget already covered. - Weekly (Monday): Filter
projects status:active type:contentsrc/lib/db/schema.ts:21→retainerprojects due <7d → setToday2worktasks from that projectscheduledDatesrc/lib/db/schema.ts:248+runDailyRolloversrc/lib/utils/task-rollover.ts:1. No weekly re-plan hunt. - Mid-cycle scope check: If
tasks>8 postsrequested, lognotesand trigger change-order → bumpprojects.budget+ spawninvoicesfor overage. Named extras keep MRR clean. - Status update: Friday
project.notes3 bullets +task statusmove →portalauto-current.
Manual retainer = you remember monthly. Linked retainer = cron + FK remembers.
Mistakes That Kill Retention
Mistake 1: One project for infinite months.
Reusing Acme Retainer project without new deadline and recurringNextDate blurs month boundaries — August vs September tasks mixed. Create monthly project or rotate deadline/tasks per cycle; invoices.projectId keeps audit.
Mistake 2: Scope as vibe 8 posts-ish.
Text 8 posts in Notion can't enforce. Tasks queue 8 todo + priority forces overflow decision. Over-delivery feels kind, teaches client boundary is joke.
Mistake 3: Billing tied to delivery, not calendar.
Invoice when posts done makes late delivery double-penalize cash flow. recurringInterval:monthly on calendar protects MRR; delivery tracked via tasks done/total separately.
Sheets / Notion / HubSpot vs Linked RunoSO
| Retainer moment | Sheets + Notion + HubSpot Deal + Calendars | RunoSO tenant_${id} 26 tables |
|---|---|---|
| Monthly invoice | Calendar ping → manual Sheet row → forget 3d → overdue | invoices recurringInterval monthly recurringNextDate + cron clone src/app/api/cron/daily/route.ts:275 auto |
Scope 8 posts | Text property → hunt Trello cards count | projects + 8 tasks projectId fk totalTasks/doneTasks src/app/api/projects/route.ts:28 count truth |
| Payment nudge | You forward DM friendly nudge | cron sent→overdue src/lib/db/schema.ts:58 + notifications + digest src/lib/emails/send.ts:469 batch |
Client Q What's done? | Build report from 4 tabs | portalTokens portal/[id] shows tasks done/total + invoices self-serve |
Credential Insta login? | Flat 1Password acme-insta 3x which? | vaultItems clientId + assetsSocial vaultItemId 1-click masked src/app/api/vault/route.ts:25 |
| Churn risk | Notice month 3 after too much back-and-forth | status active deadline <7d filter + notes boundary visible monthly |
Recurring revenue demands recurring graph.
20-Minute Retainer Setup
- Create
projectAcme — Retainer Sep 2026budget 40000type contentstatus activelinkedclientId. - Add
11 tasks8 posts + 2 updates + report — eachdueDateweekly. Create invoiceamount 40000items jsonb11 linestaxType none|GST+recurringInterval monthlyrecurringNextDate Oct 01→status sentday 1.Generate portal→ sendportal/[token]with message: Progress + invoices live here, updated Fridays, due NET-7.- Link
vaultItemsInstagram + CanvaclientId→ open dossier to confirm 1-click share next month.
Next month cron runs while you sleep. Retainer retained.
RunoSO automates retainer ops — recurring projects, linked tasks, recurringInterval invoices, and portal that shows clients what's done so they keep paying.
→ Automate Your Retainers — Try RunoSO Free
By Gautam Parmar src/app/(marketing)/about/page.tsx:44 — solo founder, Next.js 16 Tailwind v4 Neon Drizzle Razorpay Resend, building in public on X.
Keep Reading
- Keep money flowing: invoice automation draft to paid.
- Scope tight monthly: freelance scope creep stop free work.
- Assets never expire mid-retainer: hosting renewal reminders.
FAQ
How do I price retainers without hourly trap? Price by outcome ₹40k for 8 posts + 2 updates + reporting as projects.budget numeric src/lib/db/schema.ts:35 + invoices items jsonb lines — not 20 hours. Link tasks to scope; extras bill as change-order invoices — value visible via portal.
What if client asks pause? Set projects status:on-hold src/lib/db/schema.ts:21, invoices recurringNextDate null, portal shows pause progress. Filter status on-hold monthly src/lib/db/schema-public.ts:70 usageCounters to win back — not forget.
Do I need retainer contracts? Yes — include Included/Excluded, revision cap, billing calendar NET-7, pause clause. Store in project.notes and portal visibility — contract lives where work lives, not Doc you hunt.



