Railbase
GPTClaude

Licensing & pricing

Value-based module pricing (company-wide, role seat, usage, tenant/company, custom), signed license tokens, expiry, and revocation.

Updated

Video guide —watch on YouTube ↗

Business modules use value-based pricing — the metric that fits the work, not one flat per-seat rate for everything. This page explains the pricing models, what a seat is for the modules that use one, what a license is, and how your instance enforces it.

Module pricing models

The core is free to self-host. Commercial business modules are priced by the value metric that suits them:

Model pricing_kind Reads as
Free core Free to self-host
Flat company flat_monthly $X / company / month
Usage-based company plan flat_usage_monthly $X / company / month incl. quota
Billable role seat seat_monthly $X / role seat / month, viewers free
Host seat host_seat_monthly $X / host / month, participants free
Tenant / company plan tenant_monthly $X / tenant / month
Custom custom Contact sales

Each module's detail page on this site shows the model and price that apply to it. The sections below explain the role-seat model in detail, because it is the one with per-user enforcement; flat_monthly, flat_usage_monthly, and tenant/company plans do not count per-user seats. (host_seat_monthly meters a different unit — hosts — and custom is enforced however its contract specifies, so don't assume it's seat-free.)

Role-seat modules

For modules that use the billable role seat model, a license carries a seat count and your instance enforces it as described below. Modules on a flat, usage, tenant/company or custom plan do not consume seats.

What counts as a seat

A seat is a user who holds a billable role in a plugin — not every user.

  • Billable — operator- and approver-style roles that do the work (post a journal entry, approve a requisition, manage stock).
  • Free — viewers, self-service users, and public/customer roles never consume a seat.

Each plugin declares its own roles and marks which are billable; the core learns them when the signed plugin bundle is installed (see How plugins work). seats(plugin) is simply the number of users with at least one billable role in that plugin. A plugin's detail page on this site lists which roles are billable.

Note

Seats are counted per plugin. A user who operates two plugins is a seat in each. This is why adding a plugin to an existing team is priced on that plugin's billable users, not your whole user base.

What a license is

On payment, the vendor issues a short, signed license token bound to your project. On the wire it looks like:

lic1.<base64url(payload)>.<base64url(signature)>

The payload is deliberately tiny — for a role-seat module it carries { project, plugin, seats, roles, kid, iat, exp }; modules on other models carry the claims that fit their metric instead (e.g. a plan and quota, or a tenant/company scope), so it can be stored and passed around cheaply. (A license may also carry an optional node_lock that binds it to one machine's hardware fingerprint, and a trial flag for self-serve trials.) Your instance verifies the Ed25519 signature against the pinned vendor public key, then reads the seat count and expiry locally. No call to the vendor is needed to check a license; verification is offline and fast.

First activation or a move to a new machine may require a marketplace approval step before the token is bound to that node. Once bound, normal enforcement is local and continues offline. The heartbeat brings in renewals, seat changes and revocations — and it is not inbound-only: each ~60-second poll also sends this machine's hardware fingerprint (for the node-lock), the core version, and an aggregate usage snapshot.

Note

The bound seat count is enforced as a turnstile at role assignment. Once the distinct holders of a billable role reach your licensed count (per-role, or the aggregate pool on older tokens), granting that role to one more user is refused — the API returns 409 seat_limit_reached. To add a seat you must free one (revoke the role from someone) or buy more capacity on railbase.app; you can't simply add past the limit and reconcile later. The operator surface for who holds a seat is the Settings → Plugin access screen (/_/settings/plugin-access), which shows used / limit per plugin and flags an over-cap state. An over state only arises when a license downgrade drops the count below existing holders, or via an operator override — and in that case the plugin keeps running rather than bricking mid-month. The teeth are on expiry and revocation, below.

Expiry, renewal, and grace

Your instance periodically re-checks the license with the vendor (a heartbeat). This is how renewals, seat changes, and revocations propagate without you doing anything:

  • A renewed license rotates in automatically — the heartbeat re-binds the new seat count and expiry on the next tick.
  • A lapsed license (the subscription expired and no renewal re-issued one) puts the plugin dormant once grace runs out: its encrypted bundle is no longer decrypted or run, but your data is preserved untouched. Paying again issues a fresh license, and the next heartbeat re-binds it and re-activates the plugin automatically — no reinstall needed.
  • An explicitly revoked license makes the plugin dormant immediately, bypassing grace — a revoke means the bundle is no longer decrypted or run. Data is still preserved.
  • A refund or chargeback revokes the license the same way — immediately, with no grace. Reversing the payment reverses the entitlement; your data is still preserved, and re-subscribing brings the plugin back.
  • A grace window (14 days by default, set with RAILBASE_LICENSE_GRACE_DAYS; 0 disables it) covers an in-flight renewal — e.g. a webhook still settling, a payment retry over a weekend, or a box that was briefly offline — so a transient lapse doesn't suspend production. A self-serve trial gets no grace at all — it stops exactly at expiry. (The license API exposes in_grace / grace_until, though the admin doesn't currently render a grace banner from them.)

Key rotation

The vendor can rotate its signing key; the token's kid (key id) records which key signed it. To keep already-shipped binaries working across a rotation, your Railbase build pins a set of trusted vendor keys (the active key plus retired ones), and a license verifies if any pinned key accepts its signature. New licenses are signed by the current active key. A brand-new signing key is added to the pinned set in the next Railbase release — the trust root is fixed at build time, so it can't be swapped at runtime.

Managing your subscription

Buying, changing seats, switching billing cycle, and cancelling all happen on railbase.app — from your account here (the in-app admin marketplace links you out to it; there is no in-admin billing portal). Details in Managing billing.

Was this page helpful?Thanks for your feedback!