---
title: "How do you forecast renewals that don't exist as records yet?"
blueprint: 008
slug: forecasting-renewals-before-they-exist
category: Automation
revised: 2026-09-03
platform: Coevera CRM (formerly Pipeliner CRM)
canonical: https://blueprints.coevera.com/blueprints/forecasting-renewals-before-they-exist/
publisher: Coevera
customer_data: none
---

# How do you forecast renewals that don't exist as records yet?

**Short answer.** **Separate committed revenue from the renewal motion.** A signed multi-year
deal's future revenue is already in the system — a **revenue schedule** on the existing
opportunity spreads its value across dated periods (month, quarter or year), each period a record
with a date and an amount. No future deal records required.

Whether the customer *renews* is a sales question, and it needs a real opportunity. An
**opportunity recurrence rule** generates those natively — with an `AfterNMonths` or `AfterNYears`
cadence that matches a contract term rather than a calendar date.

## 01 · The business problem

A business sells on multi-year terms. Someone asks what next year's revenue looks like, and the
honest answer requires three different things that are usually treated as one:

- **Revenue already committed.** A three-year contract signed last quarter obligates the customer
  for two more years. That money is not a forecast — it is contracted, and it should not appear in
  a pipeline of things being sold.
- **Revenue that depends on a decision.** A term ending in March may or may not renew, may renew
  at a different price, may renew for a shorter period. That is genuinely a sales opportunity and
  belongs in a pipeline.
- **Revenue at risk.** A customer who cancels mid-term removes committed revenue that was already
  counted.

The requirement people state — "forecast renewals that don't exist yet" — collapses all three.
Getting a useful answer starts with pulling them apart.

## 02 · Why the obvious approach fails

### Creating dormant renewal opportunities

> **The failure is dormancy, not earliness.** A renewal opportunity created for a term two years
> out is a record sitting in the active pipeline that nobody will touch for twenty months.
> Conversion rate, average sales cycle, stage ageing and weighted forecast are all computed over
> that pipeline — fill it with deals nobody is working and every one of those numbers degrades,
> not visibly, just steadily.
>
> **But early is fine if something is driving it.** A production build we examined creates the
> renewal opportunity at the **365-day** mark and then runs a staged countdown against it: a
> quarterly-business-review task at 180 days, a customer-facing review invitation at 90, a health
> and value gate at 60, then escalating internal and customer notifications at 45, 30, 18 and 15.
> The record is never dormant, because the countdown gives somebody something to do from the day
> it appears.
>
> The rule that falls out: **create one term ahead, never several — and only alongside a cadence
> that acts on it.** A renewal opportunity with no countdown behind it is pipeline pollution
> regardless of how far out it sits.

### Putting the whole contract value on the closing date

A three-year deal booked as a single value on a single closing date says the business earned all
of it in one month. Any period-based view — monthly revenue, quarterly run-rate, ARR — is then
wrong for the entire term, in both directions: overstated in the closing month, understated in
every month after.

### Reporting on "opportunities closing next year"

The instinctive report, and it answers the wrong question. It shows deals expected to *close* next
year, which excludes every already-won contract still generating revenue next year. That is
usually the larger number, and it is missing entirely.

### Building the whole thing with automation

Understandable, and mostly unnecessary — both halves have native mechanisms. Worth checking before
building, for the same reason as [Blueprint
006](https://blueprints.coevera.com/blueprints/document-numbering-that-survives-production/),
where the commonly recommended automation workaround duplicates something that ships as a radio
button.

## 03 · Two mechanisms, two questions

An opportunity in Coevera carries both of these, and they are entirely separate things.

### Revenue schedule — what is already committed

A schedule attached to the opportunity, holding:

| Property | Meaning |
|---|---|
| `startDate` | When the revenue begins — not the closing date. |
| `periodCount` | How many periods the value spreads across. |
| `periodType` | **Month, Quarter or Year.** Those three, exactly. |
| `cancelationDate` | The contract ending early. This is where churn is expressed. |
| `periods` | The generated period records. |

Each period is its own record carrying a **date** and a **value**. That is the structure that
makes period-based reporting possible: revenue for any month is the sum of period rows dated in
it, across every contract, regardless of when those contracts closed.

### Recurrence — generating the next deal

A separate rule, also on the opportunity, that produces future opportunity records:

| Property | Meaning |
|---|---|
| `startDate` / `endDate` | The window in which occurrences are generated. |
| `stepId` | **Required** — the pipeline step generated opportunities land on. |
| `occurEvery` / `occurrencesCount` | The interval, and how many to produce. |
| `type` | The cadence — see below. |
| `day` · `dayOfWeek` · `week` · `month` | Calendar positioning, used by the absolute and relative types. |

The available cadences fall into three families:

- **Simple** — daily, weekly.
- **Absolute and relative** — monthly or yearly, either on a fixed calendar day ("the 15th") or
  relatively ("the last Friday").
- **After N** — after N days, weeks, months or years. **This is the renewal family**, because a
  renewal falls due a term after the last one rather than on a fixed date in the calendar.

> **The design decision this hands you.** Set the recurrence window so the next opportunity
> appears when someone will genuinely work it — a quarter before term end, not three years — and
> let the revenue schedule carry the committed revenue in the meantime. That keeps the pipeline
> honest and the revenue view complete at the same time, which is what the two-mechanism split is
> for.

### Distinguishing renewal from new business

Renewals usually need reporting apart from new business, which means an opportunity type. One
structural fact to plan around: **opportunity types are one-to-one with pipelines.** A space with
New Business, Expansion and Renewal as types therefore has three pipelines — which is often what
you want anyway, since a renewal moves through different steps from a new sale, but it is not a
free choice.

## 04 · What you have to add yourself

The mechanics are native; the commercial vocabulary of renewals is not. These are custom fields in
every build we have seen:

| Field | Why it is needed |
|---|---|
| Term length | The recurrence knows its interval; the record does not state the contracted term. |
| Renewal date | Distinct from the closing date, which is when the renewal *deal* closes. |
| Permitted uplift | A contractual cap on the increase — needed before the conversation, not after. |
| Billing and PO requirements | Whether this customer needs a purchase order before invoicing. Usually an account default, overridable per renewal. |
| Churn-risk indicator | Feeds re-engagement, and pairs with the cancellation date after the fact. |

The account-default-with-per-renewal-override pattern in that fourth row is worth settling early.
It is a question about where the data lives, and answering it late means moving it.

## 05 · Driving the countdown

There is no native "renewal is approaching" notification. The mechanism a production build uses
for this is worth copying, because it is simpler than it looks.

### One countdown field, many watchers

Maintain a single **"expires in days"** value on the account, and let every stage of the countdown
trigger on *changes to that one field* rather than each running its own date arithmetic. One
number ticks down; the 180-day action, the 90-day action and the 60-day action all watch it
independently.

The alternative — every process computing "is the renewal date within N days?" for itself —
multiplies the same date logic across a dozen places, and they drift.

### Make the creator idempotent with a flag

> **A daily scheduled job that creates records must be safe to run every day.** The pattern:
> filter on the countdown crossing the threshold *and* a "renewal already created" flag being
> unset; create the opportunity; set the flag.
>
> Same shape as the one-shot guard in [Blueprint
> 001](https://blueprints.coevera.com/blueprints/one-entity-five-request-types/) — the condition
> makes the write idempotent, so no separate "has this run?" bookkeeping is needed. Without it a
> daily job produces a new renewal opportunity every morning for a year.

### Exclude multi-year contracts from the annual countdown

A three-year contract should not generate renewal activity at the end of years one and two. The
production build handles this with an explicit **multi-year flag** that, combined with a
**manually-handled flag**, suppresses the standard countdown and routes those accounts to a
separate track with a special renewal date.

Worth designing in from the start. Retrofitting it means first finding every mid-contract account
that has been receiving renewal emails it should not have.

### Close the term out deliberately

When a subscription actually ends, something has to write that down. A scheduled job running the
day *after* the end date sets the loss date, stamps last-used, and clears the forward-looking
renewal fields. Without it, ended subscriptions keep appearing in renewal reporting as though
still pending.

### Two shape notes

A scheduled process filtering on a date needs a relative-period comparison rather than a fixed
value. And a process whose first node is an action rather than a filter stores successfully and
renders an empty canvas — the shape is trigger, then filter, then actions, as covered in
[Blueprint 002](https://blueprints.coevera.com/blueprints/ai-fields-read-documents/).

If the renewal opportunity should inherit anything from the expiring one — line items, the account
relation, custom field values — that is also automation. A recurrence rule generates a record at a
step; it is not a contract-copying mechanism.

## 06 · Limits & trade-offs

### Period types are month, quarter or year — nothing else

A schedule spreads across one of those three. Irregular billing — milestone payments, an uneven
ramp, a deposit followed by instalments — cannot be expressed as a native schedule. That case
needs either several opportunities or a child entity holding the payment plan, priced as in
[Blueprint 007](https://blueprints.coevera.com/blueprints/pricing-one-product-many-prices/).

### One schedule per opportunity

The schedule is a single attachment, not a collection. A deal combining, say, an annual licence
and a monthly service has two cadences and therefore needs splitting into two opportunities — a
modelling decision worth taking deliberately rather than discovering when the first such contract
arrives.

### The generated opportunity lands at a fixed step

The recurrence rule requires a target step, so every generated occurrence appears at the same
pipeline position. If renewals should enter at different stages depending on risk or size, that
routing is automation after the fact, not part of the rule.

### Stored renewal-year fields become annual maintenance

> **A trap visible only in a build that has been running for years.** If you store "this year's
> renewal", "last year's renewal" and "next year's renewal" as fields on the account — because
> reporting wants them side by side — you have signed up for an **annual re-ageing operation**.
>
> The production build we examined runs a chain of **four processes once a calendar year** to
> shift last ← this, this ← next, and next forward twelve months, with separate branches for
> multi-year contracts, and then re-derives the loss dates. It is run manually, by the person who
> remembers it exists.
>
> Derive these from the renewal date at read time wherever the reporting layer allows it. Store
> them only where you must, and if you must, write down that the rollover exists — it is exactly
> the kind of annual task that gets missed the year the person who owned it changes role.

### Schema-verified, not behaviour-verified

> **An honest boundary on this blueprint.** The orchestration in §5 and the trade-offs above are
> drawn from a build that has been running in production for years. The *native entity* half is
> weaker: the shapes, property names, period types and recurrence cadences were read directly from
> a live space's schema and are accurate, but we **did not** create a revenue schedule and watch
> periods generate, and we did not run a recurrence to completion.
>
> Two behaviours in particular remain unobserved: exactly how period records respond when a
> cancellation date is set mid-term, and whether recurrence generation is affected by the source
> opportunity being won, lost or archived. Both matter for reporting. Verify them in a sandbox
> before building a forecast on them — and note that the revenue-schedule endpoint carries no
> opportunity reference of its own, so the association is made from the opportunity side.

### The schedule cannot be attached over REST

> **Attempted and failed, so you do not have to.** The revenue-schedule endpoint has no
> opportunity reference of its own, and a create posted with one is rejected. Attaching it from
> the other direction — patching the opportunity with a schedule payload — **returns success and
> creates nothing.** A subsequent read shows no schedule in the space.
>
> That is the dominant failure mode of this platform's API, documented across this library: the
> write is accepted, no error is raised, and nothing happens. Assume schedules must be created
> through the interface or the administrative API until proven otherwise, and **always read back**
> after attempting one.

### A write quirk worth knowing

The opportunity's value reads back as a composite of base value, foreign value and currency — but
it is **written as a plain number**. Supplying the composite shape on creation was accepted and
silently produced a value of zero; the same field set as a scalar worked. If your forecast depends
on deal values arriving correctly through an integration, check them after writing.

## 07 · Verification

- **Reconcile the schedule against the deal.** The sum of period values should equal the contract
  value. If it does not, the schedule and the headline value are telling different stories and
  reports will disagree with each other.
- **Check a period-based revenue view against a closing-date view** and confirm they differ in the
  way you expect. If they match, the schedule probably is not being used.
- **Set a cancellation date on a test schedule** and observe what happens to periods after that
  date, before trusting churn reporting.
- **Let a recurrence generate at least two occurrences** and check their dates against the
  intended term — particularly with an after-N cadence, where an off-by-one interval is easy to
  configure and hard to spot.
- **Count active pipeline records before and after** enabling recurrence. If the count jumps by
  more than the next occurrence, the window is too wide and pipeline metrics are about to drift.
- **Verify deal values after any integration write**, given the composite-versus-scalar behaviour
  above.

**What would signal a regression:** period values that no longer sum to the contract value;
renewal opportunities appearing further out than the intended window; a cancelled contract still
contributing revenue to future periods; or a rising count of untouched opportunities in the active
pipeline, which is the symptom of the §2 failure returning.

---

Published by Coevera. Abstracted to the reusable pattern — no customer names, no client
data, no personal data.
