Deskie runs a single daily billing process that does three jobs in order for every active workspace: it generates recurring invoices for assignments that are due, it auto-charges saved payment methods when you have opted in, and (if configured) it auto-pauses members who fall too far behind. This article explains the cycle math, the monthly sweep, the auto-charge pass, and how billing settings control all of it.
The daily billing run
A scheduler hits a protected billing endpoint, which calls the daily billing function. That function is wired into the same per-minute cron registry as door schedules and reminders, so it is technically invoked many times a day. To prevent it from running its work repeatedly, the first invocation of each calendar day claims the run by inserting a row keyed on the run name and date. A unique constraint means every later invocation that day collides on the key and returns immediately as skipped. In practice this means the real work happens once per day.
For each workspace whose status is active, the daily run does the following in sequence:
- Monthly sweep, but only when today matches that workspace's billing anchor day.
- Non-monthly assignment billing for any daily, weekly, quarterly, yearly, or rolling-monthly assignment whose next billing date has arrived.
- Auto-charge pass, if the workspace has enabled auto-charging of unpaid invoices.
- Auto-pause, if the workspace has set an auto-pause threshold greater than zero.
The whole run is idempotent within a day. Cursors such as an assignment's next billing date and an invoice's next auto-charge timestamp only advance after a successful action, so a second pass on the same day skips anything already handled.
Billing cycle anchor: calendar vs rolling
Every recurring charge follows one of two anchoring styles, set per asset.
Calendar anchor
Calendar-anchored charges line up with fixed dates:
- Monthly charges fire on the workspace's configurable billing anchor day.
- Quarterly charges lock to January 1, April 1, July 1, and October 1. The anchor day does not affect them.
- Yearly charges lock to January 1. The anchor day does not affect them.
Rolling anchor
Rolling-anchored charges renew on the assignment's own anniversary rather than a calendar date. A rolling annual membership that starts on March 14 renews on March 14 the next year, and a rolling monthly assignment renews one month after its start date regardless of what day that lands on. Because a rolling cycle can span two calendar months, quarters, or years, its invoice line item shows the start-to-end date range instead of a label like "May 2026".
The billing anchor day
The billing anchor day is a workspace-level setting that controls which day of the month calendar-monthly charges and monthly rollups are generated. It is stored per workspace and defaults to day 1.
The setting is clamped to a value between 1 and 28. The cap at 28 exists so February never forces fallback logic for a missing 29th, 30th, or 31st.
When the anchor day is 1 (the default), the monthly cycle for any date is simply the start of that calendar month up to the start of the next month. This is identical to Deskie's original calendar-month behavior, so workspaces that never touch this setting see no change.
When the anchor day is something other than 1, say 25, the cycle that contains a given date runs from the 25th of one month to the 25th of the next. On the anchor day itself, the daily run closes out the cycle that just ended (the previous anchor day up to today) and generates invoices for it.
The monthly invoice sweep
On a workspace's anchor day, the daily run triggers the monthly sweep for that workspace. The sweep gathers everything a member owes for the closing cycle and rolls it into one consolidated invoice per member. It pulls together:
- Asset assignments billed monthly with a calendar anchor (active assignments on active assets). Rolling-monthly assignments are deliberately excluded here because they bill on their own anniversary through the non-monthly path, which avoids double billing.
- Resource bookings that were marked "add to my next invoice" and have not yet been invoiced.
- Pass purchases marked for the next invoice and not yet invoiced.
- Event tickets marked for the next invoice and not yet invoiced.
- Print jobs marked for the next invoice and not yet invoiced.
Charges are grouped by member and by billing target. A member who has a mix of personally billed and team-billed items in the same cycle produces two invoices, one addressed to the member and one addressed to the team's Stripe customer. See teams for how team billing works.
Each sweep is recorded as a run with its own date key, and a completed run for that key short-circuits any duplicate attempt, so a member cannot be double-billed for the same cycle. Invoices with a total of zero are not created. Calendar-month boundaries are computed in the workspace's timezone for the default calendar path; when the daily run supplies anchor-aware cycle bounds, those exact bounds are used instead.
Each generated invoice is created with a status of sent, a due date based on your invoice-due-days policy, and a notification email to the member summarizing the charges. For more on invoice structure, see invoices.
Non-monthly and rolling recurring charges
Charges that do not land on the calendar 1st are handled by the daily run every day, not just on the anchor day. This covers daily, weekly, quarterly, and yearly assignments, plus rolling-monthly assignments. The run looks for any active assignment on an active asset whose next billing date has arrived.
For each due assignment it generates its own individual invoice (these are not bundled with other charges), applies any active recurring coupon, sets the due date from your invoice-due-days policy, seeds the invoice for the auto-charge pass, and then advances the assignment's next billing date forward by exactly one cycle. Advancing the cursor only after a successful write is what makes reruns safe. An assignment with no rate, or a rate of zero, is skipped. A single failure is logged and the run moves on to the next assignment rather than aborting the batch.
Auto-charge of saved payment methods
Auto-charge is off by default. A workspace must explicitly enable "auto-charge unpaid invoices" for the daily run to attempt collection. When enabled, the run pulls every invoice in the workspace whose status is sent or overdue and whose next-auto-charge timestamp has arrived, then tries to charge the stored default payment method.
Invoices become eligible for auto-charge by carrying a next-auto-charge timestamp. Both the monthly sweep and the non-monthly path seed this timestamp to the invoice's due date, so collection respects your invoice-due-days policy: the first daily run on or after the due date is the first one allowed to charge.
Which payment method is used
- Member-billed invoices charge the member's saved Stripe customer and default payment method.
- Team-billed invoices prefer the team's Stripe customer and its first saved card. If the team has no card on file, the charge falls back to the member's own saved method.
Exemptions and missing setup
- Members flagged exempt from auto-billing are skipped, except on team-billed invoices, where the team is the payer rather than the member.
- If the workspace has no Stripe configured, the auto-charge pass is skipped entirely with no attempt. See connecting Stripe.
- If no payment method is on file for the resolved payer, that invoice is pushed forward by at least seven days so the run does not keep retrying it every single day.
- Invoices with a zero amount are pushed forward rather than charged.
Fees and tax on auto-charge
Auto-charge applies the same fee rules as a manual payment. The run reads the workspace's tax and card-fee configuration and computes the total on top of the invoice subtotal, skipping the card surcharge when the stored method is an ACH bank account and skipping tax when the payer is tax-exempt. When a charge succeeds, the actual fee breakdown is written onto the invoice so the receipt reflects what was charged even if you later change your fee configuration. See tax and card fees and payments and ACH.
What happens on success and failure
- Success: the invoice is marked paid, its next-auto-charge timestamp is cleared so it is never retried, a payment record is written, and an activity entry is logged.
- Failure: an activity entry records the failure, the member is sent a generic "your charge failed" email (internal error detail is not exposed to the member), and the next-auto-charge timestamp is pushed forward by the workspace's auto-charge retry days so it is attempted again later.
Batch charging across the workspace
The auto-charge pass is itself a batch operation. In a single daily run, it processes every eligible invoice for a workspace, one after another, using that workspace's own Stripe credentials. Each invoice is independent: a decline or error on one invoice is logged and deferred without stopping the rest of the batch. Stripe is instantiated once per workspace for the pass, and the workspace's currency and fee configuration are looked up once and applied to every invoice in that batch. The result of each run reports how many charges were attempted and how many succeeded.
Auto-pause for overdue invoices
Separately from charging, a workspace can set an auto-pause threshold in days. When that value is greater than zero, the daily run finds members whose oldest unpaid invoice (status sent or overdue) is past due by at least that many days and pauses their access. Team-billed invoices, already-disabled members, already-paused members, and members exempt from auto-billing are all skipped. Auto-pause does not stop billing the member, the intent is to keep charging them until they settle up, and it runs through the same path as a manual pause, including the access revoke and the pause notification email. See pausing and disabling members.
Billing settings reference
These workspace-level controls live in your finance settings and require billing-management permission to change. See workspace settings and roles and permissions.
- Billing anchor day: day of the month for monthly charges and rollups. Allowed range 1 to 28. Default 1.
- Auto-charge unpaid invoices: on or off. Default off.
- Auto-charge retry days: days to wait before retrying a failed charge on the same invoice. Allowed range 1 to 14. Default 3.
- Invoice due days: default lead time, in days from creation, for auto-generated invoices. Allowed range 0 to 90, where 0 means due on generation. Default 15. This applies to the monthly sweep, prorated charges, and non-monthly recurring charges. Manual invoices set their own due date and are unaffected.
- Auto-pause unpaid days: pause members whose oldest unpaid invoice is overdue by this many days. Allowed range 0 to 180, where 0 turns the feature off. Default 0.
