Groundwork for capping the Server plan at 100 users per server. The licensing rule itself needs no change: calculateMaxAllowedUsers already returns licenseMaxUsers when it is positive and unlimited when it is zero, which is exactly the behaviour we want once licences start carrying a real number. An un-upgraded instance therefore enforces a capped licence correctly. What did need work is the paths around it. Closes two ways past the limit. Invite links were checked when the link was generated, not when it was redeemed, so a link minted while slots were free could still create the user over the cap; redemption now re-checks and returns 409 with a message naming the limit. And saveUserCore gained a final guard, so a seventh creation path cannot be added without one. The guard needs an exemption. INTERNAL_API_USER is excluded from getTotalUsersCount, so charging its creation against the limit would strand an installation already at its cap - it could not create the account it needs to function. SaveUserRequest carries an explicit bypassUserLimit flag, set only by the three InitialSecuritySetup bootstrap paths. UserService reaches UserLicenseSettingsService through an ObjectProvider because that service already injects UserService to count users; this is the same cycle break it uses for LicenseKeyChecker. Also surfaces what the capacity UI will need: server_quantity and user_block_size read from licence metadata at all three verification paths through one helper so they cannot drift, persisted so they survive the weekly refresh, and exposed on /license-info and the admin payload. Both are presentation only; maxUsers stays the enforced limit. The admin payload also gains pendingInvites, so the UI can show what is consuming capacity - disabled accounts and unredeemed invites both hold a slot - and offer a way to reclaim it rather than making payment the only exit. No behaviour changes for any licence in the wild.
Stirling PDF - The Open-Source PDF Platform
Stirling PDF is a powerful, open-source PDF editing platform. Run it as a personal desktop app, in the browser, or deploy it on your own servers with a private API. Edit, sign, redact, convert, and automate PDFs without sending documents to external services.
Key Capabilities
- Everywhere you work - Desktop client, browser UI, and self-hosted server with a private API.
- 50+ PDF tools - Edit, merge, split, sign, redact, convert, OCR, compress, and more.
- Automation & workflows - No-code pipelines direct in UI with APIs to process millions of PDFs.
- Enterprise‑grade - SSO, auditing, and flexible on‑prem deployments.
- Developer platform - REST APIs available for nearly all tools to integrate into your existing systems.
- Global UI - Interface available in 40+ languages.
For a full feature list, see the docs: https://docs.stirlingpdf.com
Quick Start
docker run -p 8080:8080 docker.stirlingpdf.com/stirlingtools/stirling-pdf
Then open: http://localhost:8080
For full installation options (including desktop and Kubernetes), see our Documentation Guide.
Resources
Support
- Community: Discord
- Bug Reports: GitHub Issues
Contributing
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
This project uses Task as a unified command runner for all build, dev, and test commands. Run task dev to get started running the editor, run task to see the most common commands, or see the Developer Guide for full details.
For adding translations, see the Translation Guide.
License
Stirling PDF is open-core. See LICENSE for details.

