The 31st is a rule, not a date that disappears
A monthly Stripe subscription anchored on January 31 renews on February 28, or February 29 in a leap year, then March 31 and April 30. February does not permanently move the subscription to the 28th.[1] This answers a public developer question asking what happens when a subscription starts on the 31st or on leap day.[2] Treat the short-month result as an application of the anchor rule, not evidence that somebody changed the customer's schedule.
This guide concerns calendar alignment for new monthly subscriptions. It is a documentation review, not an executed Stripe integration test, and does not imply that PayIn provides Stripe subscription features. Invoice credits, unpaid-plan changes, and migration of existing subscriptions are outside scope.
Choose month-end or a numbered anniversary
Stripe documents billing_ as the way to create a monthly subscription renewing at month-end, including months with fewer than 31 days.[1] Write the intended commercial rule before choosing the parameter. “Every month's last day” and “the same numbered day as signup” are different promises.
- For month-end billing, select day 31 rather than copying whichever date happens to be the last day of the signup month.[1]
- For a leap-day anniversary, the community answer describes renewals on the 29th in other months and the 28th the following February; that is not the same sequence as month-end billing.[2]
- For a first-of-month promise, do not label a last-day timestamp as the first day of the next month. Ask the product owner to choose the actual renewal boundary.
For example, a team opening subscriptions in February might be tempted to save day 28 because that is this year's month-end. For a continuing month-end policy, use the documented day-31 configuration instead.[1] Keep the human-readable policy alongside the technical configuration so support can explain March without reverse-engineering a timestamp.
Specify the clock as well as the day
Stripe recommends billing_ for monthly or yearly subscriptions because it accounts for short months and leap years. Alternatively, billing_cycle_anchor accepts a UNIX timestamp in seconds.[1] The configuration option is documented for subscription creation; do not treat this example as an update recipe for existing customers.[1]
An illustrative configuration for month-end at midnight UTC is billing_, billing_, billing_, and billing_. Stripe supports these time components and uses UTC for the anchor.[1] These are parameter choices, not a complete payment integration or a tested request.
If hour, minute, and second are omitted, they default to the subscription creation time.[1] Setting day 31 alone therefore does not promise midnight. Record the intended UTC time and the display timezone separately. Before publishing “billed on the last day,” review how the same instant appears in the customer's timezone; do not silently substitute a local-calendar promise for a UTC configuration.
Do not confuse the anchor with the next invoice
The billing interval and anchor jointly determine the schedule. Stripe notes that a configured anchor can lie more than one billing period ahead while the first full invoice still falls within one billing period of creation or trial end.[1] An anchor is a reference point, not a universal next-charge field.
Stripe's example uses a two-month subscription created in February with day 31: the resulting anchor can be August 31, although the first full invoice is in February.[1] Keep this example as a guardrail when reviewing shared scheduling code. It does not change the ordinary monthly January–February–March sequence. Initial partial-period pricing is a separate decision; this article does not prescribe how to charge it.
Review boundaries before announcing the schedule
A second public question asks whether a January 30 subscription ending February 29 at 19:41:34 starts its next cycle at that instant or at March 1 midnight.[3] That question highlights why a date-only display is insufficient for debugging. Suggested checks below are review cases, not reported test results.
- Check a non-leap year: January 31, February 28, March 31, April 30.
- Check a leap year: January 31, February 29, March 31.
- Compare day-29 anniversary intent with day-31 month-end intent.
- Compare an explicit midnight configuration with one omitting time components.
- Record the returned anchor, actual period boundaries, interval, and displayed timezone; investigate discrepancies rather than recalculating every renewal from the previous shortened date.
The first two expected date sequences follow Stripe's documented month-end rule.[1] Use wording such as “renewal is scheduled for the last calendar day at the configured UTC time,” while showing the customer's converted timestamp where appropriate. Keep the schedule separate from any promise that payment will succeed at that instant.
Sources and dates
Official documentation supports technical behavior; community questions demonstrate qualitative demand only. Retrieved and checked on 2026-09-22. Retrieval is not publication. Unstated dates remain unknown. This is documentation research, not a live-account test, PayIn feature claim, or legal, tax or financial advice. Account eligibility and regional availability require separate confirmation.
- [1] Set the subscription billing renewal date · Publication date not stated; update date not stated · Checked 2026-09-22.
- [2] What happens when stripe billing cycle anchor is on 31st or leap year? · Published: 2019-10-02; update date not stated · Checked 2026-09-22.
- [3] Precise start and end time of subscription cycle in Stripe (with case of February) · Published: 2024-02-04; Updated: 2024-02-04 · Checked 2026-09-22.