-
Notifications
You must be signed in to change notification settings - Fork 15
Multi Tenancy Settings
Part of the Multi-tenancy section. In active development β the per-company override model is built for ticket types, ticket origins, and the Asset Management types, statuses and locations; the rest of the tabs follow the rules on this page. Building it into a new module? See the Developer Guide.
Once you have more than one company, settings naturally split into two tiers. A single-company install never sees this split β the two tiers collapse into one flat Settings, exactly as today.
Global (install-level) β things you, the operator, control once; not a client's concern, often shared across all clients:
- Connected mailboxes (the email accounts + their authentication)
- AI provider keys, outbound mail, system configuration
- The list of companies itself
- Staff accounts and their cross-company access
Per-company β things that legitimately differ from client to client (reached by selecting the company in the company switcher):
- The company's email domains and reply identity
- SLAs and business hours
- Ticket types, origins, categories, request types
- Branding
- Custom fields, forms, and knowledge-base publishing
(Note: statuses and priorities stay global on purpose β see Why some settings stay global below.)
The most important rule in the whole design:
Wherever two organisations would want different behaviour, make it a property of the thing β or a global default with per-company overrides β never an install-wide "mode" toggle.
Mode toggles force everyone into a rigid either/or and create a second source of truth that drifts out of sync. Avoiding them is what lets one install accommodate wildly different organisations. You'll see the same trick three times:
- Mailboxes β pinned vs shared is a property of each mailbox, not an "MSP mode".
- Staff β which companies an analyst can see is a property of each analyst, so a "generalist" MSP and an "account-aligned" MSP both work with no switch.
- Shared config β global default + per-company override (below).
For things whose global-vs-per-company nature is itself a matter of taste β categories, priorities, SLAs, workflows β FreeITSM won't ask you to flip a "global or per-company?" switch (changing that after you've created data is a nightmare). Instead:
- They're defined globally as sensible defaults.
- A company may override or extend them.
So an MSP that wants one standard taxonomy across every client simply never overrides β and it feels completely global. An MSP that wants each client bespoke overrides per company β and it feels completely per-company. One model, both worlds, and only one idea to learn.
Mailboxes show the split neatly:
- Connecting and authenticating a mailbox is a global action β it's infrastructure, and a shared intake mailbox doesn't belong to any single client anyway. The only new choice on that screen is pinned (pick a company) or shared.
- A company's page owns only its genuinely company-specific bits β its domains and reply identity β and shows a plain-English, read-only summary like:
"Mail arrives via the shared MyMSP intake (matched on acme.com, acme.co.uk) and a dedicated helpdesk-acme@themsp.com; replies are sent from helpdesk-acme@themsp.com."
For the settings that are lists of options a ticket points at β ticket types, ticket origins, and (coming) categories β the override works like this, while you're in a client company's context:
- Shared defaults you defined once are listed, each with a hide / show toggle (an eye icon). Hiding one removes it from that company's pickers only β every other company keeps it. The default itself is never deleted, so closed/old tickets still show the right label, and you can un-hide any time.
- The company's own items sit in their own group β add, edit and delete freely; only that company ever sees them.
- A safety rule (the in-use guard): you can't hide or delete an option while open tickets in that company still use it β reassign or close them first.
So a client that wants the standard set does nothing; a client that needs to drop one default and add two of its own takes ten seconds β without touching any other client. The shared defaults themselves are edited from the MSP / Default company context.
Not everything should be per-company, even though it could technically be made so. Three reasons a setting is deliberately kept global:
- Cross-company reporting and analyst sanity. Your analysts work across many clients, and "all open tickets" reporting only makes sense if a word means the same thing everywhere. Anything that fragments that shared meaning costs more than it gives.
- Structural invariants. Some settings carry rules the simple add/hide model can't protect β e.g. there must always be at least one "closed" status, and exactly one default. Letting a company freely hide/replace these could leave it with no way to close a ticket.
- It's the MSP's own operation, or shared infrastructure β not a client's. An analyst team, a rota, or a connected mailbox isn't owned by any one client.
| Setting | Per company? | Why |
|---|---|---|
| Ticket types | β add + hide | a plain list of options; clients genuinely differ |
| Ticket origins | β add + hide | same |
| Asset types | β add + hide | same shape as ticket types |
| Asset statuses | β add + hide | a client's asset lifecycle can differ (note: ticket statuses stayed global β a judgement call per module) |
| Asset locations | β per company | a tree of a client's physical sites β entirely the company's own (no shared locations; a client with a London office doesn't inherit anyone else's) |
| Suppliers | β shared | one registry shared with Contracts & RFP; a client's private suppliers would leak into those until they're scoped too β kept shared for now |
| Categories / request types | β (planned) | same |
| Departments | β (planned, with extra care) | a department is inside a client β but it's wired to teams, mailbox routing and SLAs, so it needs more than a simple list |
| SLAs & business hours | β (planned) | contractual per client β the headline per-company setting |
| Statuses | β global | structural invariants (closed/default) + cross-company reporting needs shared meaning |
| Priorities | β global | a default priority + the SLA targets hang off them, so they're the stable axis SLAs vary against |
| Teams, analysts, rota | β global | the MSP's own operation; who sees which client is handled by staff access, not by copying teams per client. (A global team can grant its members access to specific clients β additive access, not a per-client copy of the team.) |
| Mailboxes, AI keys, outbound mail | β global | shared infrastructure; a shared intake mailbox spans every client |
| General / CSAT / reply-cleanup | β global (per-company value override later if needed) | these are single settings, not lists β a different override shape |
The guiding rule: default to global; add a per-company override only where a client genuinely needs to differ β and pick the override shape that fits (add/hide for option-lists, a per-company value for single settings, nothing for things the MSP owns).
FreeITSM β an open-source IT Service Management platform Β· github.com/edmozley/freeitsm Β· MIT licence
- Installation
- β° Scheduled tasks (cron jobs)
- Architecture
- AI Providers
- Internationalisation (i18n)
- Timezones & Time Handling
- Theming & Dark Mode
- β¨οΈ Command palette (βK)
- π Searching inside tickets
- π Attached documents
- MobileβFriendly
-
Security
- Layer 1 β which modules you can enter
- β³ π§© Module Access Control
- β³ π οΈ Module Access β Developer Guide
- Layer 2 β what you can administer
- β³ π Roles & Permissions
- β³ π οΈ Roles β Developer Guide
- β³ π€ Why capabilities are constants
- Layer 3 β the System module
- β³ π Admin Access Control
- Hardening
- β³ π Security review response 2026-08
- β³ π‘οΈ Security hardening 2026-08
- β³ π οΈ Security hardening 2026-08 β Developer Guide
- β³ π‘οΈ Round three β plain English
- β³ π οΈ Round three β Developer Guide
- Single Sign-On (SSO)
- ποΈ LDAP & Active Directory
- Browser Extension
- API Reference
-
π REST API β how it works
- β³ π« REST API: Tickets
- β³ π» REST API: Assets
- β³ π΄ REST API: Problems
- β³ π REST API: Changes
- β³ π REST API: Knowledge
- β³ β REST API: Tasks
- β³ ποΈ REST API: CMDB
- β³ π REST API: Contracts
- β³ ποΈ REST API: Calendar
- β³ πΏ REST API: Software
- β³ π¦ REST API: Service Status
- β³ βοΈ REST API: Morning Checks
- β³ π REST API: Forms
- β³ βοΈ REST API: Workflow
- β³ πΊοΈ REST API: Network Mapper
- β³ π§ Using the API docs page
- β³ π OpenAPI specification
- β³ β OpenAPI: kept correct
- β³ π οΈ Maintaining the catalogue
- Watchtower
-
Tickets
- β³ Mailbox Authentication
- β³ π€ Email send log
- β³ Basic IMAP mailboxes
- β³ Email rendering & images
- β³ SLA Management
- β³ WhatsApp channel
- β³ π¬ Web chat channel
- β³ π£ Slack channel
- β³ π Linking tickets
- β³ ποΈ Canned responses
- β³ βοΈ Limiting replies to particular senders
- β³ βοΈ Email signatures
- β³ π The public web address
- β³ π’ Ticket numbering
- β³ π Raising a ticket for someone else
- β³ π Merging tickets
- β³ β Splitting tickets
- β³ β Selecting several tickets
- β³ ποΈ The folder pane
- β³ π οΈ Snoozing tickets β Developer Guide
- β³ π₯ Collision detection
- β³ β±οΈ Time tracking
- Problem Management
- Tasks
- Assets
- Knowledge
- Change Management
- Calendar
- Morning Checks
- Reporting
- Software
- Forms
- Contracts
- Service Status
- π Notifications
- π¨ War Room
- Self-Service Portal
- LMS
- Process Mapper
- CMDB
- Network Mapper
- Workflows
- Issue trackers (Jira, Azure DevOps)
- System
-
Overview
- β³ π Progress tracker
- β³ Concepts & vocabulary
- β³ Email routing & mailboxes
- β³ Settings: global vs per-company
- β³ Users & self-service
- β³ Staff cross-company access
- β³ Worked examples
- β³ Pitfalls & gotchas
- β³ Scope: what it's for
- β³ π οΈ Developer Guide (make a module multi-company)
- β³ ποΈ Case study: CMDB (a linked graph)
- β³ π§ͺ Test harness (prove it's isolated)