---
title: Billing Cycles
description: "A billing cycle is a term you sell on — monthly, quarterly, annually. Every recurring price in RackHelm hangs off one, for products and for add-on options alike, so this is the first screen to visit on a new install.…"
url: "https://rackhelm.com/documentation/billing-cycles/"
updated: "2026-09-24"
category: "Products & Catalogue"
---

# Billing Cycles

A billing cycle is a term you sell on — monthly, quarterly, annually. Every recurring price in RackHelm hangs off one, for products and for add-on options alike, so this is the first screen to visit on a new install. This article is for operators.

## Before you start

> **Note:** The route is gated by `edit_products`, and the controller additionally checks an `admin_panel` capability that is not one of the seeded permissions — so in a default install only **Super Admin** can open and change this screen. The sidebar link itself is shown under `manage_products`, which is also not seeded. See [Roles & Permissions](/docs/roles-and-permissions/).

> **Warning:** A fresh install has **no** billing cycles. Until you create at least one, the product editor's pricing table shows "No billing cycles defined yet" and the add-on editor refuses to price anything.

## The Billing Cycles screen

Open **Catalogue → Billing Cycles** (`/admin/billing-cycles`). It is a single table, and both creating and editing happen in the same modal.

![The Billing Cycles table listing label, term, usage count, status and sort order](/wp-content/uploads/rackhelm-docs/catalogue-billing-cycles-index.png)
The **Used By** badge counts how many products carry a price for that cycle — that is exactly what a delete would wipe.

| Column | Shows |
| --- | --- |
| **Label** | The customer-facing name. |
| **Term** | The length in months, rendered as "12 months". A cycle stored with a term of zero renders as "One-time". |
| **Used By** | "N products" — the number of product price rows pointing at this cycle. Cycles with none read "Unused". |
| **Status** | **Active** or **Inactive**. |
| **Sort** | The sort order value. |

## Creating or editing a cycle

Click **New Billing Cycle**, or **Edit** on a row. The same modal serves both; it retitles itself and pre-fills from the row you clicked.

![The shared New/Edit Billing Cycle modal with label, months, sort order and an Active switch](/wp-content/uploads/rackhelm-docs/catalogue-billing-cycle-modal.png)
Four fields, and the **Months** value must be unique across the whole install.

| Field | Rules and effect |
| --- | --- |
| **Label** | Required, up to 255 characters. This is what customers see at checkout and in the cycle selector, so write it the way you want it read — "Annually", "1 Year", "Every 3 months". |
| **Months** | Required whole number, minimum 1, and **unique** — you cannot have two cycles of the same length. This drives renewal scheduling and the savings calculator, so it must be the real term, not a label. |
| **Sort Order** | Optional integer, minimum 0, defaults to `0`. Lower numbers appear first in the Billing Cycles list, the product editor's pricing table and the customer's cycle selector. The add-on pricing grid ignores it and orders its columns by term length instead. |
| **Active** | Defaults to on for a new cycle. See below for exactly what it gates. |

> **Note:** Because **Months** has a minimum of 1, you cannot create a genuine one-off (zero-month) cycle through this form, even though the list will render one correctly if it exists in the database. Model one-off charges as a product with a base price and no billing cycle instead — but be aware that add-ons can only be priced against a cycle, so a one-off product cannot carry priced add-ons.

## What Active actually controls

The **Active** flag is a soft retirement switch, not a kill switch:

- Inactive cycles are **excluded** from the add-on editor's pricing grid, so you cannot add new add-on pricing against them.
- Inactive cycles **still appear** in the product editor's billing-cycle table, so an existing product's pricing for that cycle stays visible and editable.
- Existing orders and invoices already on the cycle are unaffected — nothing is re-priced or migrated.

The screen states this in its own words at the foot of the table: cycles marked Inactive stay on existing orders but are hidden from new product and add-on pricing.

## Deleting a cycle

There is no protective check. Deleting a cycle removes it immediately. Add-on option prices for that cycle are cascade-deleted by the database; the product price rows have no foreign key, so they survive as orphans pointing at a cycle that no longer exists — invisible in the product editor and unusable at checkout, which amounts to the same loss. The confirmation dialog tells you how many products are affected before you commit:

> **Warning:** Deleting a cycle that is in use permanently loses the pricing for every product and every add-on option priced against it. There is no undo. If your intent is "stop selling this term", set it **Inactive** and clear its prices from the products instead.

## Choosing a sensible set

A cycle is cheap to add but disruptive to remove, so decide the shape up front. A common hosting set:

| Label | Months | Sort Order |
| --- | --- | --- |
| Monthly | 1 | 0 |
| Quarterly | 3 | 1 |
| Semi-Annually | 6 | 2 |
| Annually | 12 | 3 |
| Biennially | 24 | 4 |

Domain products usually need 1, 2, 3, 5 and 10 *years* — that is 12, 24, 36, 60 and 120 months, each as its own cycle.

> **Tip:** Turn on **Show Cycle Savings** on a product group once you have more than one cycle priced. The order page then works out and displays the saving of each longer term against the shortest priced term of a month or more.

## Troubleshooting

| Symptom | Cause and fix |
| --- | --- |
| "The months has already been taken." | Another cycle already uses that term length. Terms are unique — edit the existing cycle's label rather than creating a duplicate. |
| The Billing Cycles link is missing from the sidebar. | It is shown under the `manage_products` key, which has no permission record and so cannot be granted from the Roles screen — only Super Admin sees it. Navigate to `/admin/billing-cycles` directly. |
| A new cycle does not appear in an add-on's pricing grid. | The add-on editor lists active cycles only. Reopen the cycle and switch **Active** on. |
| Prices vanished from several products after a delete. | Their price rows still point at the deleted cycle, so nothing can resolve them. Restore from a database backup — the application has no undo for this. |
| Cycles appear in the wrong order at checkout. | The customer's cycle selector orders purely by **Sort Order**. Give each cycle a distinct sort order. |
| An add-on cannot be priced at all. | Add-on prices are stored per cycle and the cycle reference is mandatory, so an order with no billing cycle has nothing for its add-ons to price against. Sell add-ons only alongside products that use a billing cycle. |
