Administration & hosting

Billing, sign-in & email setup

Turn on paid plans with Stripe, configure Google/GitHub sign-in and support email.

Pricing and costs

Launch prices, flat per workspace (the billing code charges one Stripe price per workspace, so member caps stand in for per-seat pricing):

Plan Per month Orgs Members CI jobs Deployments / month Backup storage
Free $0 3 3 2 100 (no backups, no test monitoring, no data deploys) 1 GB
Team $149 10 5 25 5,000 5 GB
Business $349 30 15 100 20,000 25 GB
Enterprise quote unlimited unlimited unlimited unlimited unlimited

Backup storage is counted from the files a workspace's backups, snapshots, archives and deployment packages point at. At the limit, new backups pause (scheduled, record, archive and Marketing Cloud ones; manual backups are refused with a clear message), the owners get an email at most once a week, and nothing is deleted. Free trials and billing-off have no limit.

For scale, Gearset charges roughly $215 to $320 per user per month for DevOps, plus separate backup fees, so 5 users cost $1,000 to $1,600 a month there against $149 here. Yearly billing at ten months' price (two free) is the plan once Stripe is set up. Existing databases pick up the change through migration 29 (only while the old $99 "Pro" plan is untouched and has no Stripe price); Admin → Plans always has the last word.

Add-ons (paid plans only): a workspace can add capacity on top of its plan, billed per unit each month. Launch prices: Extra backup storage is $10 per 10 GB, and Extra deployments is $20 per 5,000 a month. Each unit is one more line quantity on the Stripe subscription, prorated for the current month; the owner changes it under Settings → Plan & billing (Need more room?), and the extra room counts straight away. A limit that is already unlimited stays unlimited. Prices, how much a unit adds and the Stripe price ids are edited in Admin → Plans → Add-ons. Stripe needs one monthly recurring price per add-on (the price of one unit); the subscription webhook keeps each workspace's quantities in step, and cancelling the plan clears them. Storage costs about $0.03 per GB a month at current cloud prices, so the add-on is a healthy margin; raise the price if your costs rise.

What it costs to run (monthly, approximate, check current prices before relying on them):

Item Now When it grows
Server (Oracle Always Free VM) $0 about $50 to $100 if you outgrow the free ARM allowance
Disk and backups $0 (200 GB free; the Storage card in Admin shows use) about $0.03 per GB per month beyond that
Domain $0 (DuckDNS) about $1 (yearly fee spread out)
Email (Brevo) $0 (free daily quota) about $10 to $25 for a paid tier
AI assistance $0: customers use their own API keys none
CI/CD (GitHub Actions) $0 within the free minutes stays $0 (local deploy fallback)
Stripe fees none until a sale about 3% plus $0.30 per charge, a little more with Stripe Tax: about $5.50 on $149

Running costs are near zero today and perhaps $100 to $150 a month once you pay for a bigger server, a domain and email, so one Team customer ($149, about $143 after fees) covers everything. What the table leaves out is yours to add: the business registration and accounting, income tax, and your own time. Break-even on the infrastructure is one customer; break-even on a salary is a number only you can set (at $149 per Team customer, ten customers is about $1,400 a month).

Watch two things as customers arrive: the Storage card (move to a bigger disk before it reaches 80%), and the email quota.

Deleting workspaces that never paid

Off by default. Set DELETE_AFTER_DAYS (for example 60) and, once BILLING_ENABLED is on, the worker deletes a workspace that is that many days past the end of its unpaid trial, together with its stored backups and files. Safeguards:

  • Only workspaces on the paywall (new sign-ups and admin-granted trials) still in the unpaid trialing state. Anything with a Stripe subscription, or a paid status, is never touched.
  • Never a workspace with Never delete this workspace's data switched on (Admin → Accounts → the workspace), a suspended one, or one containing a platform admin.
  • Owners get two emails: 14 days and 3 days before. Deletion happens at least a day after the final warning, and never in the same pass as a warning.
  • Each deletion is recorded in the platform audit log (team.delete.expired, actor system).
  • The trial emails state the deletion period. Choosing a plan at any point stops it.

Before turning it on: put the retention period in the Terms and the sign-up notice. A deleted workspace also stays in older database backups until they rotate out.

Free now, paid later

Diffbridge launches free. With BILLING_ENABLED=false (the default), every workspace gets every feature with no limits, and the Billing tab says "Free during early access".

All the paid-tier code is already in place. To start charging:

  1. In Stripe, create a product per paid plan, each with a monthly recurring price. Copy each price id (price_…).
  2. In Admin → Plans, edit each plan (Free / Pro / Enterprise, or add your own): set the price, the limits and features, and paste the Stripe price id.
  3. In Stripe, go to Developers → Webhooks and add the endpoint https://<your-domain>/api/billing/webhook with these events: checkout.session.completed, customer.subscription.created, customer.subscription.updated and customer.subscription.deleted. Copy the signing secret.
  4. Set these and restart:
    BILLING_ENABLED=true
    STRIPE_SECRET_KEY=sk_live_…
    STRIPE_WEBHOOK_SECRET=whsec_…
    
  5. Enable the Customer portal in Stripe's Billing settings, so "Manage billing" can open it.

Once billing is on:

  • Every new workspace gets a free trial of TRIAL_DAYS (default 30) from sign-up: every feature, no limits, no card needed. Workspaces created before billing was turned on have no trial and are never locked automatically; to give one a trial, open Admin → Accounts and set the status to trialing with a trial until date.
  • After the trial, unpaid, a workspace is read-only. It can still sign in, view and export its data, reach billing and support; every change is refused with a "free trial has ended" message, and automation (CI webhooks and schedules, backups, deployments) stops too. Paying (an active subscription), an Enterprise plan or a plan comped from the admin panel lifts it at once. A platform admin keeps the admin panel even when their own workspace is locked.
  • Trial emails go to the workspace owners 7 days before the trial ends, 1 day before, and when it has ended (once each, and only while billing is on). Each links to Plan & billing.
  • Limits are enforced when someone adds an org, invites a member, creates a CI job, or starts a deployment (per calendar month). Features (backups, test monitoring, data deploy, pipelines) are checked when they're used.
  • Team owners upgrade from Settings → Plan & billing through Stripe Checkout and manage cards and invoices in Stripe's portal.
  • Stripe webhooks keep each team's plan and status in sync. They're signature-verified and processed exactly once.
  • A canceled or unpaid subscription, or a trial that ended unpaid, puts the team in the read-only state above (the Free plan is the fallback tier for limits, not a way to keep using the product).

Admin panel (/admin)

Only platform admins can see it; everyone else gets a 404. Grant access with PLATFORM_ADMIN_EMAILS=a@x.com,b@y.com.

Tab What you can do
Overview Accounts, users, 30-day signups, active teams, MRR, accounts per plan, whether Stripe and email are configured, and Storage: how full the disk is, the size of stored backups, snapshots and packages, the database size, and the largest workspaces
Accounts Search and filter teams. Open one to change its plan or status, grant a trial until a date, override individual limits (including unlimited), add internal notes, suspend or unsuspend, and see members and orgs. Delete the account (you type its name to confirm)
Users Search everyone, see their sign-in methods (password, Google, GitHub), last login and pending invites, and disable or enable a user, which takes effect immediately
Plans Edit or add plans: price, Stripe price id, limits, features, whether it's public, whether it's active
Support inbox Every support request, suggestion and bug report, filterable by status and type. Reply opens your mail client to the sender. Mark items in progress or resolved
Audit log Every admin action and Stripe-driven change: who did it, what, and when

A suspended workspace can still sign in, view its data, contact support and reach billing, but every change is blocked until you unsuspend it.

Sign in with Salesforce, Google, LinkedIn and GitHub

  • Google: in Google Cloud Console, go to APIs & Services → Credentials, create an OAuth client ID of type Web application, and add the authorized redirect URI https://<your-domain>/api/auth/oauth/google/callback. Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET.
  • GitHub: go to Settings → Developer settings → OAuth Apps → New OAuth App, and set the callback URL to https://<your-domain>/api/auth/oauth/github/callback. Set GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET.
  • LinkedIn: at linkedin.com/developers create an app, add the product Sign In with LinkedIn using OpenID Connect, and add the redirect URL https://<your-domain>/api/auth/oauth/linkedin/callback. Set LINKEDIN_CLIENT_ID and LINKEDIN_CLIENT_SECRET.
  • Salesforce (two buttons: Production/Developer and Sandbox): uses the packaged Salesforce app that Connect org uses. Add the callbacks https://<your-domain>/api/auth/oauth/salesforce/callback and https://<your-domain>/api/auth/oauth/salesforce_sandbox/callback to it, make sure its OAuth scopes include openid, email and profile, then set SF_LOGIN_ENABLED=true. (SF_LOGIN_CLIENT_ID and SF_LOGIN_CLIENT_SECRET use a different app instead.) Only people whose Salesforce org has the app installed can use it.

The buttons appear on the sign-in page once a provider is configured.

Account merging: when the provider returns a verified email that matches an existing Diffbridge user, the Google or GitHub identity is linked to that user instead of creating a new account. A pending invite is accepted the same way. Unverified provider emails are never merged. Salesforce is the exception: an org's admins control the emails of its users, so a Salesforce email never merges into an existing account. A new person can sign in with Salesforce to create an account, but to use Salesforce with an account that already exists, sign in another way once and link Salesforce there. A sandbox user can only sign in after linking, because sandbox emails are not real addresses. Users can also link or unlink providers, and set a password, under Settings → My account.

Two-step sign-in (authenticator app)

Password sign-in can ask for a 6-digit code from an authenticator app (TOTP, RFC 6238, SHA-1, 30 seconds, one step either side). Each person sets it up under Settings → My account, and gets ten one-time recovery codes. Details worth knowing:

  • The secret is stored encrypted with the server key; recovery codes are stored as keyed hashes. A used code cannot be replayed, and five wrong codes lock the second step for five minutes.
  • It only applies to password sign-in. Google, LinkedIn, Salesforce and SAML sessions are not asked (those services do their own checks).
  • A password reset link does not sign anyone in who has it on, so the link cannot bypass the second step.
  • Owners can require it for the workspace (Settings → Security); people without it are limited to the setup screens until they finish. Owners can reset a teammate's second step (Settings → Team → Reset 2-step); every use is in the audit log (mfa.enable, mfa.disable, mfa.reset, mfa.require, mfa.recovery.used, mfa.locked). API tokens are not affected and cannot change these settings.
  • If the only owner of a workspace loses both their phone and recovery codes, a Diffbridge operator has to clear it in the database (update users set mfa_secret_enc = null, mfa_enabled_at = null where email = '...'), after verifying who they are.

Contact support, suggestions and bug reports

Help & feedback, in the sidebar or the ⌘K palette, sends a support request, a suggestion or a bug report (with severity, plus the page and browser version if the user allows it). Signed-out users can reach support from the sign-in page.

  • Every message is saved to the admin inbox first, so nothing is lost if email fails.
  • It's then emailed to SUPPORT_EMAIL with Reply-To set to the sender, so you can just hit reply.
  • SUPPORT_EMAIL is server-only. It never appears in an API response, in the UI or browser bundle, or in the server logs, and it isn't committed to git. A test checks every API response for it.

Email delivery uses one of:

  • EMAIL_PROVIDER=smtp with SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER, SMTP_PASS. This works with Gmail (use an app password: smtp.gmail.com, port 465, secure), Amazon SES, Postmark and others.
  • EMAIL_PROVIDER=resend with RESEND_API_KEY.
  • EMAIL_PROVIDER=log (local default): nothing is sent, and the message is still stored in the inbox.
Something unclear or missing on this page?