Menu
Dev.to #architecture·August 13, 2026

Designing a Robust Workflow with Minimal State Machine for Contract Registration

This article details the system design considerations for an Ejar contract registration workflow, focusing on the request lifecycle from validation to registration. Key architectural decisions include designing a lean state machine and carefully ordering operations for financial integrity. It highlights the importance of clear data validation and traceable transactions in complex workflows.

Read original on Dev.to #architecture

The article presents the engineering decisions behind designing a workflow for registering lease contracts with Saudi Arabia's Ejar platform. The core challenge lies in managing the request lifecycle accurately, ensuring data integrity, and handling financial transactions while interacting with an external government system that strictly verifies identities and data.

Lean State Machine Design

A crucial architectural decision was to resist the temptation of creating numerous states for every minor nuance in the workflow. Instead, the design employs a minimal state machine with only four states. The principle guiding this decision is that a state should only exist if it dictates a difference in system behavior, not just a different description of the request's status.

  • PENDING: Awaiting processing.
  • IN_PROGRESS: Currently being processed.
  • COMPLETED: Successfully registered, requires an Ejar contract number.
  • REJECTED: Rejected due to invalid data, requires a reason, triggers automatic refund, and allows retry.
💡

State Machine Design Principle

Only introduce a new state if it fundamentally changes the system's operational logic or available actions. Each additional state adds complexity to queries, dashboards, and migrations.

Ensuring Financial Integrity and Traceability

The sequence of operations during contract request creation is critical, especially concerning financial transactions. The system prioritizes data validation *before* any money is debited. This prevents unnecessary charges for incomplete or incorrect data, which is essential when dealing with external, strict validation systems.

  1. Validate Completeness: All contract data is validated first. If incomplete, a `BadRequestException` is thrown with specific missing fields.
  2. Compute Fees: Fees are calculated only after successful validation.
  3. Debit Wallet: The user's wallet is debited for the calculated fees.
  4. Create Request: The Ejar request is created with a `PENDING` status.
  5. Back-link Wallet Transaction: The wallet transaction is linked back to the newly created Ejar request, ensuring full traceability of funds.
typescript
// 1. Validate completeness - before anything that costs money
const missingFields = this.validateContractData(contract);
if (missingFields.length > 0) {
  throw new BadRequestException({
    message: 'Contract data is incomplete for electronic registration',
    missingFields,
  });
}
// 2. Compute fees
// 3. Debit
// 4. Create the request
// 5. Back-link the wallet transaction to the request
state machineworkflow designtransactional integrityAPI integrationerror handlingdata validationmicroservices architecture

Comments

Loading comments...
Designing a Robust Workflow with Minimal State Machine for Contract Registration | SysDesAi