Lewati ke konten utama

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.