Skip to content

Freemium vs Pro

PerfShop applies a freemium model: part of the platform is accessible without a license to allow discovery and onboarding, and the rest is unlocked by activating a commercial license. This page describes precisely the boundary between the two.

Sources

backend/src/main/java/com/perfshop/service/LicenseService.java, chaos/LicenseInterceptor.java, controller/ChaosStudentController.java, controller/ChaosScriptingPublicController.java

Philosophy

A student should be able to get started with PerfShop immediately, without formality. They should be able to navigate the shop, run a first performance chaos, try a first scripting level, and start the first two levels of the pedagogical journey (BAC1 and BAC2). This is more than enough for a convincing demonstration in class or in an assessment.

What constitutes intensive use in continuing education or in enterprise — the full business chaos, OWASP security flaws, advanced scenarios, the expert pedagogical journey — requires a license.

The commercial license also includes access to a turnkey lab library hosted separately, which is not distributed with the PerfShop source code and is not documented here.

Summary table

Chaos family Without license (freemium) With license
Backend performance Level 0 + Level 1 (freemium N1) Levels 0 to 4 + 20 weather scenarios
Scripting Level 0 + Level 1 (Junior) Levels 0 to 4 (up to Maestro)
Frontend Level 0 only Levels 0 to 4
Business Level 0 only Levels 0 to 4 (16 anomalies A1-A16)
Functional Level 0 only Levels 0 to 4 (F1-F4)
Security Level 0 only Levels 0 to 4 (S1-S12, admin portal S10-S12 at Master level)
Pedagogical BAC1, BAC2 BAC1 to BAC5
Instructor interface Without license With license
chaos-admin (instructor panel) ❌ Blocked ✅ Accessible
scripts-ui (web script editor) ❌ Blocked ✅ Accessible (plan functional+)
jmeter-ui (JMeter launcher) ❌ Blocked ✅ Accessible (plan performance+)
monitoring (admin login) ❌ Blocked ✅ Accessible
Admin backoffice /api/admin/* ❌ Blocked ✅ Accessible
Student interface Without license With license
Student page chaos-admin/public/ ✅ Accessible ✅ Accessible
E-commerce shop ✅ Accessible ✅ Accessible
Read-only HTML monitoring dashboard ✅ Accessible ✅ Accessible
MkDocs documentation ✅ Accessible ✅ Accessible

What is always accessible

These resources are never blocked by the LicenseInterceptor, regardless of the license:

  • /api/license/* — activation, status, revocation (otherwise deadlock)
  • /api/chaos/student/* — the freemium student page
  • /api/chaos/public/* — read-only pedagogical monitoring
  • /api/products/* — shop catalog
  • /api/auth/* — shop authentication
  • /api/cart/* — cart
  • /api/checkout/* — checkout funnel
  • /api/orders/* — orders
  • /api/countries — country reference data
  • /actuator/* — Prometheus scraping
  • /images/* — product assets

See License system for the exhaustive list and the interception logic.

HTTP 402 Payment Required

When a protected endpoint is called without a valid license, the backend responds:

HTTP/1.1 402 Payment Required
Content-Type: application/json;charset=UTF-8
X-License-Required: true

{
  "error":       "LICENSE_REQUIRED",
  "message":     "License required to access chaos-admin",
  "path":        "/api/chaos/backend",
  "activateUrl": "/api/license/activate",
  "statusUrl":   "/api/license/status",
  "portalUrl":   "https://perfshop.io"
}

The HTTP code 402 is deliberately chosen — it means exactly "payment required". The HTTP spec reserved it for future use related to micropayments; it is rarely used in practice, which makes it a clear and unambiguous signal. The PerfShop frontends (chaos-admin, scripts-ui, jmeter-ui) detect this code and display a redirect message to the activation portal rather than a generic error.

The additional X-License-Required: true header allows programmatic clients (curl, CI scripts) to detect the case without parsing the JSON.

Freemium enforcement in code

The LicenseInterceptor handles URL-based authorization. For finer freemium endpoints (Scripting level 1 allowed, levels 2+ blocked), enforcement goes through the controllers themselves which consult licenseService.isLicenseValid() and limit the maxLevel returned in the /status payloads.

For example, ChaosStudentController returns for each chaos family an object { level, maxLevel }. Without a license, maxLevel is 1 for scripting (Junior freemium) and 0 for business, functional, security. With a license, maxLevel becomes 4 for all families.

The frontend uses this value to visually lock the sliders: slider.max = maxLevel and slider.disabled = (maxLevel === 0). See Student chaos page.

Master level (cumulative level 4)

Level 4 of each family is nicknamed "Master" in the interfaces. It requires an active license but is also qualitatively different:

  • Business Master (A12-A16) — 5 silent anomalies with high financial impact, invisible without inspecting the JSON payloads
  • Security Master (S10-S12) — chained scenario on the vulnerable admin portal (see Admin portal and Security Chaos)
  • Functional Master (F4) — silent corruption: no crash, green Tempo, HTTP 200, but corrupted payload
  • Scripting Master — HMAC key derived per session (more demanding in reverse engineering)
  • Performance Master — N4 weather scenarios combining several simultaneous chaos types
  • Pedagogical Master (BAC5) — longest journey, passwords built with XOR + Pi computation

The Master level is the target of the most advanced training sessions. It is included in all plans (functional, performance, enterprise).

Activation from the student page

An important detail: the student page remains accessible without a license, and it includes a "🔑 Activate a license" button in the header that calls POST /api/license/activate. This endpoint is itself public (see License system).

Practical consequence in a classroom: the instructor can give a key to a test student, who activates it from their workstation — and all other students immediately benefit from the unlocked levels, because the license is shared at the server level, not at the browser session level. This property is a direct consequence of the model: one license per PerfShop instance, not per user.

What happens when the license expires?

On every call, isLicenseValid() checks the current date against expiresAt:

public boolean isLicenseValid() {
    LicenseInfo info = cachedLicense.get();
    if (info == null) return false;
    if (info.expiresAt == null) return true;
    return !LocalDate.now().isAfter(info.expiresAt);
}

The switch is immediate: starting the day after expiration, all calls to protected endpoints return 402. The shop, the student page and the HTML monitoring remain accessible — meaning that students can continue to see what they have already launched but can no longer start new chaos. Historical Grafana dashboards remain browsable.

To extend, simply activate a new key via POST /api/license/activate — no restart is necessary.

Purchasing a license

PerfShop commercial licenses are distributed by perfshop.io. The terms (number of instances, duration, training, support) are negotiated directly. Contact contact@perfshop.io to obtain a quote.

The license purchase also includes access to the turnkey lab library, which is hosted separately and is not documented in this technical reference.