SaaS Revenue Recognition
Modeling deferred and realized revenue for subscription-based businesses.
SaaS Revenue Recognition
In a subscription business, you often collect payment upfront for a service delivered over time. According to accounting standards (like ASC 606), you cannot recognize the full payment as revenue immediately. Instead, you move it to Deferred Revenue and "earn" it monthly.
Architecture
We use two distinct ledgers to separate the cash you've received from the revenue you've actually earned.
Implementation Flow
Setup Ledgers
Create one ledger for the liability (money owed in service) and another for the actual business income.
# Liability Ledger
curl -X POST http://localhost:8080/v1/ledgers -d '{ "name": "Deferred Subscriptions" }'
# Income Ledger
curl -X POST http://localhost:8080/v1/ledgers -d '{ "name": "Realized SaaS Revenue" }'Record Upfront Payment
When a customer pays $1,200 for an annual plan, you debit your bank account (Asset) and credit their Deferred Revenue account (Liability).
curl -X POST http://localhost:8080/v1/transfers
-d '{
"debit_account_id": "BANK_CASH_ID",
"credit_account_id": "CUSTOMER_DEFERRED_ID",
"amount": 120000,
"code": 1000 # Code: "Subscription Payment"
}'Monthly Revenue Recognition
Every month, you move $100 from the customer's Deferred account to your Realized Revenue ledger.
curl -X POST http://localhost:8080/v1/exchanges
-d '{
"source_account_id": "CUSTOMER_DEFERRED_ID",
"destination_ledger_id": "REALIZED_REVENUE_LEDGER_ID",
"amount": 10000,
"code": 2000 # Code: "Revenue Recognition"
}'Advanced Scenarios
1. Handling Cancellations & Refunds
If a customer cancels mid-year and is entitled to a refund, you simply reverse the flow for the remaining balance.
# Refund $600 of the remaining $1,200
curl -X POST http://localhost:8080/v1/transfers \
-d '{
"debit_account_id": "CUSTOMER_DEFERRED_ID",
"credit_account_id": "BANK_CASH_ID",
"amount": 60000,
"code": 3000 # Code: "Subscription Refund"
}'2. Plan Upgrades (Proration)
When a customer upgrades from a $100/mo plan to a $200/mo plan mid-month:
- Calculate the remaining days of the old plan.
- Move the unused portion back to a temporary "Credit" account.
- Charge the new plan amount minus the credit.
Why this matters
- Audit Readiness: Your balance sheet correctly shows how much service you still owe to customers.
- Churn Impact: If a customer cancels mid-year, the remaining balance in
CUSTOMER_DEFERREDis exactly what you need to refund. - Financial Clarity: You see your "Earned Revenue" month-over-month, providing a true picture of business growth regardless of when the cash hit the bank.
Automation Tip: In production, you typically trigger the "Monthly Recognition" step using a workflow engine like Temporal, ensuring that the recognition happens exactly on the subscription anniversary every month.