Gateway Use Cases
This page provides real-world examples of how to use each gateway type in common business scenarios.
Table of Contents
- Loan Application Processing
- Customer Onboarding
- Transaction Approval Workflow
- Fraud Detection
- Document Processing
- Customer Notification System
- Risk Assessment
- Account Closure
Loan Application Processing
Complete Workflow
A comprehensive loan application process using all three gateway types.
BPMN Implementation
<!-- 1. EXCLUSIVE: Route by amount -->
<bpmn:exclusiveGateway id="Gateway_Amount" default="Flow_Standard">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
return loanAmount > 50000 ? 'Flow_Senior' : 'Flow_Standard';
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:outgoing>Flow_Senior</bpmn:outgoing>
<bpmn:outgoing>Flow_Standard</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- 2. PARALLEL: Background checks -->
<bpmn:parallelGateway id="Gateway_ChecksSplit">
<bpmn:outgoing>Flow_ToCredit</bpmn:outgoing>
<bpmn:outgoing>Flow_ToEmployment</bpmn:outgoing>
<bpmn:outgoing>Flow_ToIdentity</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:serviceTask id="Task_CreditCheck" name="Credit Bureau Check" />
<bpmn:serviceTask id="Task_Employment" name="Employment Verification" />
<bpmn:serviceTask id="Task_Identity" name="Identity Verification" />
<bpmn:parallelGateway id="Gateway_ChecksJoin">
<bpmn:incoming>Flow_FromCredit</bpmn:incoming>
<bpmn:incoming>Flow_FromEmployment</bpmn:incoming>
<bpmn:incoming>Flow_FromIdentity</bpmn:incoming>
<bpmn:outgoing>Flow_ToRisk</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- 3. EXCLUSIVE: Risk decision -->
<bpmn:exclusiveGateway id="Gateway_Risk">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
const riskScore = calculateRiskScore(creditScore, employmentYears, debtToIncome);
if (riskScore < 30) return 'Flow_Approve';
if (riskScore < 70) return 'Flow_Review';
return 'Flow_Reject';
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:outgoing>Flow_Approve</bpmn:outgoing>
<bpmn:outgoing>Flow_Review</bpmn:outgoing>
<bpmn:outgoing>Flow_Reject</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- 4. INCLUSIVE: Notifications -->
<bpmn:inclusiveGateway id="Gateway_Notify" default="Flow_Email">
<bpmn:outgoing>Flow_Email</bpmn:outgoing>
<bpmn:outgoing>Flow_SMS</bpmn:outgoing>
<bpmn:outgoing>Flow_Push</bpmn:outgoing>
</bpmn:inclusiveGateway>
<bpmn:sequenceFlow id="Flow_SMS" sourceRef="Gateway_Notify" targetRef="Task_SMS">
<bpmn:conditionExpression>customerPhone !== null</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_Push" sourceRef="Gateway_Notify" targetRef="Task_Push">
<bpmn:conditionExpression>hasMobileApp === true</bpmn:conditionExpression>
</bpmn:sequenceFlow>
Key Points:
- Exclusive for routing decisions (amount threshold, risk assessment)
- Parallel for independent checks that can run simultaneously
- Inclusive for notifications through available channels
Customer Onboarding
Scenario
New customer registration with conditional verification steps.
Requirements
- All customers: Email verification, basic profile setup
- Corporate customers: Business verification, tax ID validation
- High-value customers: Additional reference checks
- International customers: Address verification via third-party
Implementation
<!-- Determine customer type -->
<bpmn:exclusiveGateway id="Gateway_CustomerType">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
return customerType; // 'INDIVIDUAL', 'CORPORATE', 'INTERNATIONAL'
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:exclusiveGateway>
<!-- For all customer types: Basic verification (parallel) -->
<bpmn:parallelGateway id="Gateway_BasicVerify">
<bpmn:outgoing>Flow_EmailVerify</bpmn:outgoing>
<bpmn:outgoing>Flow_ProfileSetup</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- Conditional additional checks (inclusive) -->
<bpmn:inclusiveGateway id="Gateway_AdditionalChecks" default="Flow_Complete">
<bpmn:outgoing>Flow_Complete</bpmn:outgoing>
<bpmn:outgoing>Flow_BusinessVerify</bpmn:outgoing>
<bpmn:outgoing>Flow_ReferenceCheck</bpmn:outgoing>
<bpmn:outgoing>Flow_AddressVerify</bpmn:outgoing>
</bpmn:inclusiveGateway>
<!-- Business verification for corporate -->
<bpmn:sequenceFlow id="Flow_BusinessVerify"
sourceRef="Gateway_AdditionalChecks"
targetRef="Task_BusinessVerify">
<bpmn:conditionExpression>
customerType === 'CORPORATE'
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<!-- Reference check for high-value -->
<bpmn:sequenceFlow id="Flow_ReferenceCheck"
sourceRef="Gateway_AdditionalChecks"
targetRef="Task_ReferenceCheck">
<bpmn:conditionExpression>
estimatedTransactionVolume > 100000
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<!-- Address verification for international -->
<bpmn:sequenceFlow id="Flow_AddressVerify"
sourceRef="Gateway_AdditionalChecks"
targetRef="Task_AddressVerify">
<bpmn:conditionExpression>
country !== 'US' && country !== 'CA'
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
Execution Examples
| Customer Type | Additional Checks Activated |
|---|---|
| Individual, US, low-value | None (just basic) |
| Corporate, US, low-value | Business verification |
| Individual, UK, high-value | Address verification + Reference check |
| Corporate, International, high-value | All three additional checks |
Transaction Approval Workflow
Multi-Level Approval Based on Amount and Type
<bpmn:exclusiveGateway id="Gateway_AmountCheck">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
// Route based on amount and transaction type
if (transactionType === 'WIRE_INTERNATIONAL' && amount > 10000) {
return 'Flow_ComplexApproval';
}
if (amount > 100000) {
return 'Flow_ExecutiveApproval';
} else if (amount > 50000) {
return 'Flow_ManagerApproval';
} else if (amount > 10000) {
return 'Flow_OfficerApproval';
} else {
return 'Flow_AutoApprove';
}
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:exclusiveGateway>
<!-- Complex approval requires parallel checks -->
<bpmn:parallelGateway id="Gateway_ComplexApproval">
<bpmn:outgoing>Flow_ToCompliance</bpmn:outgoing>
<bpmn:outgoing>Flow_ToFraud</bpmn:outgoing>
<bpmn:outgoing>Flow_ToManager</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:userTask id="Task_ComplianceReview" name="Compliance Review">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="AssignedRole" value="ComplianceOfficer" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:userTask>
<bpmn:serviceTask id="Task_FraudCheck" name="Fraud Detection Check" />
<bpmn:userTask id="Task_ManagerApproval" name="Manager Approval">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="AssignedRole" value="TransactionManager" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:userTask>
<!-- All three must complete -->
<bpmn:parallelGateway id="Gateway_ComplexJoin">
<bpmn:incoming>Flow_FromCompliance</bpmn:incoming>
<bpmn:incoming>Flow_FromFraud</bpmn:incoming>
<bpmn:incoming>Flow_FromManager</bpmn:incoming>
<bpmn:outgoing>Flow_ToFinalDecision</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- Final decision based on all approvals -->
<bpmn:exclusiveGateway id="Gateway_FinalDecision">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
// All must approve
if (complianceApproved && !fraudDetected && managerApproved) {
return 'Flow_Execute';
} else {
return 'Flow_Decline';
}
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:exclusiveGateway>
Flow Diagram:
Fraud Detection
Real-Time Multi-Check System
<!-- Initial screening (parallel checks) -->
<bpmn:parallelGateway id="Gateway_FraudScreening">
<bpmn:outgoing>Flow_ToVelocityCheck</bpmn:outgoing>
<bpmn:outgoing>Flow_ToPatternMatch</bpmn:outgoing>
<bpmn:outgoing>Flow_ToBlacklistCheck</bpmn:outgoing>
<bpmn:outgoing>Flow_ToGeoCheck</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:serviceTask id="Task_VelocityCheck" name="Velocity Check">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Command" value="CheckTransactionVelocity" />
<custom:property name="Parameters" value='{
"customerId": "{customerId}",
"timeWindowMinutes": 60,
"maxTransactions": 10
}' />
</custom:properties>
</bpmn:extensionElements>
</bpmn:serviceTask>
<bpmn:serviceTask id="Task_PatternMatch" name="Pattern Matching" />
<bpmn:serviceTask id="Task_BlacklistCheck" name="Blacklist Check" />
<bpmn:serviceTask id="Task_GeoCheck" name="Geolocation Check" />
<!-- Wait for all checks -->
<bpmn:parallelGateway id="Gateway_FraudJoin">
<bpmn:incoming>Flow_FromVelocity</bpmn:incoming>
<bpmn:incoming>Flow_FromPattern</bpmn:incoming>
<bpmn:incoming>Flow_FromBlacklist</bpmn:incoming>
<bpmn:incoming>Flow_FromGeo</bpmn:incoming>
<bpmn:outgoing>Flow_ToRiskScore</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- Calculate risk score -->
<bpmn:scriptTask id="Task_CalculateRisk" name="Calculate Risk Score">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
let riskScore = 0;
if (velocityExceeded) riskScore += 30;
if (suspiciousPattern) riskScore += 25;
if (onBlacklist) riskScore += 40;
if (geoMismatch) riskScore += 20;
// Additional factors
if (newDevice) riskScore += 10;
if (unusualTime) riskScore += 5;
totalRiskScore = riskScore;
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>
<!-- Risk-based decision -->
<bpmn:exclusiveGateway id="Gateway_RiskDecision">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
if (totalRiskScore >= 60) {
return 'Flow_Block';
} else if (totalRiskScore >= 30) {
return 'Flow_Review';
} else {
return 'Flow_Allow';
}
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:exclusiveGateway>
<!-- If review needed, conditional additional checks (inclusive) -->
<bpmn:inclusiveGateway id="Gateway_AdditionalChecks" default="Flow_HumanReview">
<bpmn:outgoing>Flow_HumanReview</bpmn:outgoing>
<bpmn:outgoing>Flow_CustomerContact</bpmn:outgoing>
<bpmn:outgoing>Flow_DocumentRequest</bpmn:outgoing>
</bpmn:inclusiveGateway>
<bpmn:sequenceFlow id="Flow_CustomerContact"
sourceRef="Gateway_AdditionalChecks"
targetRef="Task_ContactCustomer">
<bpmn:conditionExpression>
totalRiskScore >= 40
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_DocumentRequest"
sourceRef="Gateway_AdditionalChecks"
targetRef="Task_RequestDocuments">
<bpmn:conditionExpression>
totalRiskScore >= 50 || onBlacklist === true
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
Risk Scoring:
| Risk Score | Action | Additional Steps |
|---|---|---|
| 0-29 | Allow | None |
| 30-39 | Review | Human review only |
| 40-49 | Review | Human review + Customer contact |
| 50-59 | Review | Human review + Customer contact + Documents |
| 60+ | Block | Immediate block, no additional steps |
Document Processing
Parallel Document Validation
<!-- Customer uploads multiple documents -->
<bpmn:parallelGateway id="Gateway_ProcessDocuments">
<bpmn:outgoing>Flow_ProcessPassport</bpmn:outgoing>
<bpmn:outgoing>Flow_ProcessProofAddress</bpmn:outgoing>
<bpmn:outgoing>Flow_ProcessIncomeProof</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- Each document processed independently -->
<bpmn:serviceTask id="Task_ValidatePassport" name="Validate Passport">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Command" value="ValidateIdentityDocument" />
<custom:property name="Parameters" value='{
"documentType": "PASSPORT",
"documentId": "{passportDocumentId}",
"checks": ["OCR", "MRZ_VALIDATION", "EXPIRY_CHECK", "FRAUD_DETECTION"]
}' />
</custom:properties>
</bpmn:extensionElements>
</bpmn:serviceTask>
<bpmn:serviceTask id="Task_ValidateAddress" name="Validate Proof of Address" />
<bpmn:serviceTask id="Task_ValidateIncome" name="Validate Income Proof" />
<bpmn:parallelGateway id="Gateway_DocumentsJoin">
<bpmn:incoming>Flow_FromPassport</bpmn:incoming>
<bpmn:incoming>Flow_FromAddress</bpmn:incoming>
<bpmn:incoming>Flow_FromIncome</bpmn:incoming>
<bpmn:outgoing>Flow_ToReview</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- Review results -->
<bpmn:scriptTask id="Task_ReviewResults" name="Review Validation Results">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Count passed validations
const passed = [
passportValid,
addressValid,
incomeValid
].filter(v => v === true).length;
allDocumentsValid = (passed === 3);
partiallyValid = (passed >= 2);
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>
<!-- Decision based on results -->
<bpmn:exclusiveGateway id="Gateway_DocumentDecision">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
if (allDocumentsValid) {
return 'Flow_Approve';
} else if (partiallyValid) {
return 'Flow_RequestResubmit';
} else {
return 'Flow_Reject';
}
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:exclusiveGateway>
Customer Notification System
Comprehensive Multi-Channel Notifications
<bpmn:inclusiveGateway id="Gateway_NotificationChannels">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
const channels = [];
// Email: Always included if available
if (customerEmail) {
channels.push('Flow_Email');
}
// SMS: For urgent notifications or if preferred
if (customerPhone && (notificationUrgency === 'HIGH' || preferredChannel === 'SMS')) {
channels.push('Flow_SMS');
}
// Push: If app installed and notifications enabled
if (hasMobileApp && pushNotificationsEnabled) {
channels.push('Flow_Push');
}
// In-App: If currently logged in
if (isActiveSession) {
channels.push('Flow_InApp');
}
// WhatsApp: For international customers with WhatsApp
if (hasWhatsApp && country !== 'US') {
channels.push('Flow_WhatsApp');
}
return channels.join(',');
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:outgoing>Flow_Email</bpmn:outgoing>
<bpmn:outgoing>Flow_SMS</bpmn:outgoing>
<bpmn:outgoing>Flow_Push</bpmn:outgoing>
<bpmn:outgoing>Flow_InApp</bpmn:outgoing>
<bpmn:outgoing>Flow_WhatsApp</bpmn:outgoing>
</bpmn:inclusiveGateway>
Notification Matrix:
| Scenario | SMS | Push | In-App | ||
|---|---|---|---|---|---|
| Low urgency, US, logged out | ✓ | ✗ | ✗ | ✗ | ✗ |
| High urgency, US, logged in | ✓ | ✓ | ✓ | ✓ | ✗ |
| Low urgency, International, app user | ✓ | ✗ | ✓ | ✗ | ✓ |
| High urgency, International, no app | ✓ | ✓ | ✗ | ✗ | ✓ |
Risk Assessment
Comprehensive Risk Evaluation
<!-- Parallel data collection -->
<bpmn:parallelGateway id="Gateway_DataCollection">
<bpmn:outgoing>Flow_ToCreditData</bpmn:outgoing>
<bpmn:outgoing>Flow_ToTransactionHistory</bpmn:outgoing>
<bpmn:outgoing>Flow_ToExternalData</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:serviceTask id="Task_FetchCreditData" name="Fetch Credit Data" />
<bpmn:serviceTask id="Task_AnalyzeTransactions" name="Analyze Transaction History" />
<bpmn:serviceTask id="Task_FetchExternalData" name="Fetch External Risk Data" />
<bpmn:parallelGateway id="Gateway_DataJoin">
<bpmn:incoming>Flow_FromCredit</bpmn:incoming>
<bpmn:incoming>Flow_FromTransactions</bpmn:incoming>
<bpmn:incoming>Flow_FromExternal</bpmn:incoming>
<bpmn:outgoing>Flow_ToCalculation</bpmn:outgoing>
</bpmn:parallelGateway>
<!-- Calculate risk score -->
<bpmn:scriptTask id="Task_CalculateRisk" name="Calculate Risk Score">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Script" value="
// Weighted risk calculation
const creditRisk = (850 - creditScore) / 8.5; // 0-100 scale
const transactionRisk = calculateTransactionRisk(transactionHistory);
const externalRisk = externalRiskScore;
// Apply weights
totalRisk = (creditRisk * 0.4) + (transactionRisk * 0.35) + (externalRisk * 0.25);
// Categorize
if (totalRisk < 30) riskCategory = 'LOW';
else if (totalRisk < 60) riskCategory = 'MEDIUM';
else riskCategory = 'HIGH';
" />
</custom:properties>
</bpmn:extensionElements>
</bpmn:scriptTask>
<!-- Route based on risk -->
<bpmn:exclusiveGateway id="Gateway_RiskRouting">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="return 'Flow_' + riskCategory;" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:outgoing>Flow_LOW</bpmn:outgoing>
<bpmn:outgoing>Flow_MEDIUM</bpmn:outgoing>
<bpmn:outgoing>Flow_HIGH</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Medium risk: Additional conditional checks (inclusive) -->
<bpmn:inclusiveGateway id="Gateway_MediumRiskChecks" default="Flow_ManagerReview">
<bpmn:outgoing>Flow_ManagerReview</bpmn:outgoing>
<bpmn:outgoing>Flow_AdditionalVerification</bpmn:outgoing>
<bpmn:outgoing>Flow_CreditEnhancement</bpmn:outgoing>
</bpmn:inclusiveGateway>
<bpmn:sequenceFlow id="Flow_AdditionalVerification"
sourceRef="Gateway_MediumRiskChecks"
targetRef="Task_AdditionalVerification">
<bpmn:conditionExpression>
transactionRisk > 50
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="Flow_CreditEnhancement"
sourceRef="Gateway_MediumRiskChecks"
targetRef="Task_RequestCollateral">
<bpmn:conditionExpression>
creditRisk > 60
</bpmn:conditionExpression>
</bpmn:sequenceFlow>
Account Closure
Conditional Cleanup Tasks
<bpmn:inclusiveGateway id="Gateway_CleanupTasks">
<bpmn:extensionElements>
<custom:properties>
<custom:property name="Condition" value="
const tasks = [];
// Always close the account
tasks.push('Flow_CloseAccount');
// Transfer funds if balance > 0
if (accountBalance > 0) {
tasks.push('Flow_TransferFunds');
}
// Cancel cards if any active
if (hasActiveCards) {
tasks.push('Flow_CancelCards');
}
// Cancel standing orders if any
if (hasStandingOrders) {
tasks.push('Flow_CancelStandingOrders');
}
// Cancel direct debits if any
if (hasDirectDebits) {
tasks.push('Flow_CancelDirectDebits');
}
// Archive data
tasks.push('Flow_ArchiveData');
return tasks.join(',');
" />
</custom:properties>
</bpmn:extensionElements>
<bpmn:outgoing>Flow_CloseAccount</bpmn:outgoing>
<bpmn:outgoing>Flow_TransferFunds</bpmn:outgoing>
<bpmn:outgoing>Flow_CancelCards</bpmn:outgoing>
<bpmn:outgoing>Flow_CancelStandingOrders</bpmn:outgoing>
<bpmn:outgoing>Flow_CancelDirectDebits</bpmn:outgoing>
<bpmn:outgoing>Flow_ArchiveData</bpmn:outgoing>
</bpmn:inclusiveGateway>
Cleanup Matrix:
| Account State | Tasks Executed |
|---|---|
| Basic account, $0 balance | Close + Archive |
| Account with balance | Close + Transfer + Archive |
| Account with cards | Close + Cancel Cards + Archive |
| Full account with all features | All 6 tasks |
Summary
Gateway Selection Guide
| Scenario | Use Gateway | Reason |
|---|---|---|
| Choose approval level | Exclusive | One approver needed |
| Run background checks | Parallel | Independent, simultaneous |
| Send notifications | Inclusive | Multiple optional channels |
| Route by amount | Exclusive | Single path based on threshold |
| Collect data sources | Parallel | Independent data fetching |
| Additional verification | Inclusive | Conditional extra checks |
| Risk-based routing | Exclusive | One risk category |
| Document validation | Parallel | Independent document checks |
| Cleanup tasks | Inclusive | Conditional cleanup based on state |
Best Practices from Use Cases
- Use Exclusive for binary/categorical decisions - Approve/Reject, Risk Level, Amount Ranges
- Use Parallel for independent tasks - Background checks, Data collection, Document processing
- Use Inclusive for optional parallel tasks - Notifications, Additional checks, Cleanup tasks
- Combine gateways for complex flows - Exclusive routing → Parallel checks → Inclusive notifications
- Calculate before deciding - Use ScriptTask to prepare data, then gateway to route
- Always have fallback - Set default flows on Exclusive and Inclusive gateways
Next Steps
- See detailed documentation for Exclusive Gateway
- See detailed documentation for Parallel Gateway
- See detailed documentation for Inclusive Gateway
- Visit Troubleshooting for common issues