ERP Licensing Architecture Proposal
Background
Current ERP product is implemented as a .NET Monolith and is being transformed into a commercial ERP product that can be:
- Hosted by vendor (SaaS / Managed Hosting)
- Installed on customer infrastructure (On-Premise)
- Migrated gradually toward Microservices architecture
The objective of this proposal is to introduce a licensing mechanism that:
- Is simple for Phase 1
- Does not embed complex licensing logic inside ERP modules
- Supports future feature-based licensing
- Supports future user limits
- Supports future machine fingerprint restrictions
- Supports future subscription models
- Can evolve seamlessly into a Microservices ecosystem
Design Principles
1. License is a Platform Concern
ERP business modules should not be responsible for:
- License generation
- License signing
- Subscription management
- Customer entitlement management
These concerns belong to the platform layer.
2. License Must Be Extensible
Avoid fixed schema such as:
{
"maxUsers": 50
}
Instead use:
{
"features": {},
"limits": {},
"constraints": {}
}
This allows future expansion without redesign.
3. ERP Consumes Entitlements
ERP should consume entitlements through a dedicated License Service.
ERP should not need to know:
- How licenses are generated
- How licenses are signed
- How subscriptions are managed
ERP only asks:
Is feature X available?
What is the limit for Y?
High-Level Architecture
flowchart TD
Portal[portal.erp.com]
Portal --> TenantRegistry[Tenant Registry]
Portal --> Provisioning[Provisioning Service]
Portal --> LicenseMgmt[License Management]
Portal --> SubscriptionMgmt[Subscription Management]
Provisioning --> Ticket[Provisioning Ticket]
Ticket --> CustomerA
Ticket --> CustomerB
subgraph Customer A Environment
DNSA[client-a.app.erp.com]
ERPA[ERP Instance]
LicenseA[License Service]
DBA[(ERP Database)]
DNSA --> ERPA
ERPA --> LicenseA
ERPA --> DBA
end
subgraph Customer B Environment
DNSB[client-b.app.erp.com]
ERPB[ERP Instance]
LicenseB[License Service]
DBB[(ERP Database)]
DNSB --> ERPB
ERPB --> LicenseB
ERPB --> DBB
end
LicenseMgmt --> LicenseA
LicenseMgmt --> LicenseB
Portal Components
Tenant Registry
Stores:
- Customer
- Tenant
- Domain
- Environment
- Deployment Metadata
Example:
TenantId
CompanyName
Domain
Status
CreatedAt
Provisioning Service
Responsible for:
- Creating DNS
- Deploying ERP Instance
- Creating Database
- Initial License Deployment
Subscription Management
Responsible for:
- Trial
- Monthly Subscription
- Annual Subscription
- Perpetual License
- Support Contract
License Management
Responsible for:
- Generate License
- Sign License
- Renew License
- Upgrade Features
- Revoke License
Customer Runtime Architecture
Each customer deployment contains:
flowchart LR
ERP[ERP Application]
LS[License Service]
LIC[license.lic]
DB[(ERP Database)]
ERP --> LS
LS --> LIC
ERP --> DB
License Service Responsibilities
License Service is responsible for:
- Reading license file
- Verifying signature
- Checking expiration
- Evaluating limits
- Returning entitlements
ERP never reads the license file directly.
ERP Integration Contract
ERP communicates with License Service using a simple abstraction.
Example:
public interface ILicenseProvider
{
bool HasFeature(string featureCode);
int GetLimit(string limitCode);
LicenseInfo GetLicenseInfo();
}
Example usage:
if (_licenseProvider.HasFeature("finance"))
{
ShowFinanceMenu();
}
License File Structure
Version 1
{
"licenseId": "LIC-2026-0001",
"tenantId": "TENANT001",
"edition": "Professional",
"subscription": {
"type": "annual",
"expiresAt": "2027-12-31"
},
"features": {
"sales": true,
"purchase": true,
"inventory": true,
"finance": false
},
"limits": {
"users": 50
},
"constraints": {
"machineFingerprint": null
}
}
Future Expansion
The same schema can support:
Module Licensing
{
"features": {
"sales": true,
"inventory": true,
"finance": false,
"manufacturing": true,
"quality_control": true
}
}
User Limits
{
"limits": {
"users": 100
}
}
Branch Limits
{
"limits": {
"branches": 5
}
}
Warehouse Limits
{
"limits": {
"warehouses": 20
}
}
Machine Binding
{
"constraints": {
"machineFingerprint": "ABC123XYZ"
}
}
License Security
Signing Strategy
Portal owns:
Private Key
License Service owns:
Public Key
Flow:
sequenceDiagram
participant Portal
participant LicenseFile
participant LicenseService
Portal->>LicenseFile: Generate Payload
Portal->>LicenseFile: Sign Payload
LicenseService->>LicenseFile: Verify Signature
LicenseFile-->>LicenseService: Valid License
Benefits:
- License cannot be modified by customer
- ERP remains unaware of signing process
- Licensing logic remains centralized
Microservices Readiness
Future architecture:
flowchart LR
Sales[Sales Service]
Inventory[Inventory Service]
Finance[Finance Service]
Manufacturing[Manufacturing Service]
LicenseService[License Service]
Sales --> LicenseService
Inventory --> LicenseService
Finance --> LicenseService
Manufacturing --> LicenseService
Each service consumes the same entitlement API.
No licensing logic needs to be duplicated.
Phase 1 Scope
Implement:
- Portal License Management
- License Generator
- License Signing
- Local License Service
- Feature Entitlement API
- Subscription Expiration Validation
Do Not Implement Yet:
- Online Activation
- Machine Fingerprint Enforcement
- Concurrent User Enforcement
- Usage-Based Billing
- Cloud Validation
These can be introduced later without changing the architecture.
Conclusion
The proposed architecture separates licensing concerns from ERP business logic while remaining compatible with both SaaS and On-Premise deployments.
By introducing a dedicated License Service and extensible license schema from the beginning, the platform can evolve from a .NET Monolith into a Microservices ERP ecosystem without redesigning the licensing foundation.