Connect by JBRH Open Connect

Enforcing an allowance, end to end

The last unit of an allowance is claimed by a conditional update, so two simultaneous attempts cannot both win it. The one that loses gets a coded refusal before any provider is called. Nothing it was carrying is discarded: the draft stays, the approval stays recorded, and mail ingestion holds its read position. At the next daily reset the same work proceeds untouched.

Status
Available What this means
Audience
customer
In the app
#/billing, #/needs-you
Last verified
Product version
6.3.2

The approach#

Enforcement is not a check followed by an action — that pattern loses the race between two requests reading the same remaining count. The reservation *is* the check: today's usage row is claimed if it does not exist, then incremented by a conditional update that only succeeds while there is room. Whichever request the database serves second is refused, and it is refused before anything has been handed to a provider.

A caller that reserves repeatedly against one workspace — the mail sync, reserving once per message — reads the plan facts once for the batch, because a transaction sees the same plan for every message in it. What is never batched is the reservation itself: the conditional update runs for each unit, and that is the part that makes the limit authoritative.

The refusal#

ReasonWhat happenedClears when
Daily allowance spentToday's count reached the plan's limit for that dimensionThe next daily reset, on the UTC date boundary
Plan not activeThe entitlement is not in an active or trialing stateThe plan is settled — see A plan lapsing
Dated plan endedA plan with an end date has passed itThe plan is renewed or changed
Resource ceiling reachedOne more of a thing cannot exist — a mailbox slot, for instanceSomething is removed, or the plan allows more

Each refusal carries its own code rather than a single generic message, which is what lets a screen say *the allowance is spent* instead of *try again*. The distinction matters because the two conditions have different waiting times: one clears on a clock, the other does not clear at all without somebody acting.

Stage by stage#

  1. Trigger — a metered action reaches the reservation with the day's allowance already at its limit.
  2. User or external event — often nobody is watching. The engine's own drain hits the limit far more often than a person pressing send does.
  3. Authentication and workspace resolution — already settled; the reservation refuses outright if the plan facts it was handed belong to a different workspace than the one being charged.
  4. Ingest or request — the caller asks for one unit of a named dimension inside its own transaction.
  5. Canonical record — the conditional update does not match, so today's usage row is unchanged. A refusal writes nothing except the record of itself.
  6. Reasoning — none is spent, on purpose. Drafting a reply that cannot be sent costs a model call and produces something nobody may use.
  7. Knowledge, memory and rules — untouched.
  8. Autonomy and approval — unchanged. A held item does not lose its approval because the send was refused; the approval was a decision and it stands.
  9. Action through a provider — none. The refusal happens before provider work, which is why there is never a half-sent message to reconcile.
  10. Result — a coded refusal, and the item stays exactly where it was in the queue.
  11. Relationship, timeline and memory — the conversation is not marked answered. A refused send never becomes a sent one in anybody's history.
  12. Audit, usage and Needs You — the refusal is recorded as a decision with its reason, and the blockage surfaces for a person rather than only in a log.

What is held#

An approved draft
Stays approved and stays queued. Approving again does nothing useful; the item is waiting on allowance, not on a decision.
The mail read position
Does not advance over refused messages. Advancing it would mark a window done and the refused mail would never be fetched again — not late, gone.
A phone follow-up
Left for a later tick rather than closed, unless it is more than a day late, in which case it is closed as missed and never rung. A very late call-back is worse than none.
An inbound message already delivered
Kept. Inbound is counted for reporting and is never used to refuse.

The resume#

  1. Wait for the daily reset, or change the plan so the limit is higher.

    Result The next reservation succeeds. There is no restart, no cache to clear and no queue to rebuild.

  2. Let the mail sync run again.

    Result It resumes from the position it held, so the refused messages are ingested in order.

  3. Check the held items before releasing a batch of them.

    Result Anything the customer has already followed up on is caught before it goes out as a duplicate answer.

A reservation that succeeded for work that then failed is released rather than left spent — otherwise a provider outage would consume a whole day's allowance on messages nobody ever received, which is a limit doing damage rather than its job.

Questions#

When exactly does the allowance reset?

On the UTC date boundary. The usage row is keyed by workspace, dimension and UTC date, so a new date is simply a new row starting at zero — there is no scheduled job to fail and nothing to sweep.

If two sends race for the last unit, can both go out?

No. The claim is a conditional update rather than a read followed by a write, so exactly one of them succeeds and the other is refused before it reaches a provider. That property is the reason the check and the increment are the same statement.

Does hitting an allowance affect what Connect may do?

No. Autonomy is unchanged: a workspace on an autonomous channel is still autonomous, it simply has nothing left to spend. Permission and allowance are separate systems and neither one silently edits the other.