Back to blog
architecturecommand-pipelinedeep-divebackend

AuraBoot's 20+ Stage Command Pipeline Explained

AuraBoot Team|

An inside look at AuraBoot's 20+ stage command pipeline — the engine behind data operations from CRUD to multi-step business transactions.

AuraBoot's 20+ Stage Command Pipeline Explained

Every time you create a record, update a status, or approve a workflow in AuraBoot, your operation passes through a 20+ stage pipeline. The point is not ceremony; it is to keep validation, permissions, side effects, audit, and integrations in one predictable path.

Why a Pipeline?

Traditional approaches scatter business logic across controllers, services, interceptors, and database triggers. When something goes wrong, you're debugging across four layers of code. When you need to add a validation, you're modifying service classes that handle dozens of operations.

AuraBoot's pipeline centralizes all data mutation logic into a single, ordered sequence. Each stage has a clear responsibility, runs in a defined order, and is configurable per-command through the DSL.

The Core Stages

Stage 1: Request Parsing

Raw HTTP request is parsed into a structured CommandRequest object. Field values are type-coerced to match the model definition. Unknown fields are rejected.

Stage 2: Authentication

Verifies the JWT token and resolves the current user, tenant, and session context. The MetaContext is populated and available to all subsequent stages.

Stage 3: Permission Check

The command's permissionCode is checked against the user's role assignments. AuraBoot supports:

  • Model-level permissions (can this user access leads?)
  • Command-level permissions (can this user convert leads?)
  • Field-level permissions (can this user see the revenue field?)

Stage 4: Entitlement Check

For SaaS deployments, this stage verifies that the tenant's subscription tier allows the requested operation. A tenant on the Free plan might be limited to 1,000 records per model.

Stage 5: Pre-Validation

Schema-level validations run first: required fields, data type matching, length constraints, unique checks. These are fast, stateless checks that catch obvious errors before any business logic executes.

Stage 6: Field Defaults

Default values are computed and applied to missing fields:

{
  "fieldDefaults": {
    "status": "NEW",
    "assigned_to": "${CURRENT_USER}",
    "due_date": "${DATE_ADD(NOW, 7, 'DAY')}",
    "code": "${AUTO_NUMBER('ORD', 6)}"
  }
}

Expressions have access to the current user, tenant, record context, and built-in functions.

Stage 7: Business Validation

Custom validation rules that require business context:

{
  "businessValidation": {
    "rules": [
      {
        "field": "quantity",
        "operator": "LTE",
        "valueFrom": "product.stock_quantity",
        "message": "Quantity exceeds available stock"
      }
    ]
  }
}

These rules can reference other models and perform cross-entity checks.

Stage 8: Computed Fields

Fields whose values derive from other fields:

{
  "computedFields": {
    "total_amount": "${quantity * unit_price}",
    "tax_amount": "${total_amount * tax_rate}",
    "grand_total": "${total_amount + tax_amount}"
  }
}

The computation engine handles dependency ordering automatically.

Stage 9: Pre-Hooks

Extension point for custom Java logic that must run before the data mutation. Used sparingly — most logic should be declarative.

Stage 10: Confirmation

For destructive operations, the pipeline can pause and request user confirmation:

{
  "confirmMessage": "$i18n:order.confirm_cancel"
}

Stage 11: Data Mutation

The actual database write. CREATE inserts a new record. UPDATE modifies existing fields. DELETE performs a soft delete (or hard delete for dynamic entities).

Stage 12: Post-Hooks

Extension point for custom logic after the mutation. Access to both the previous and current record state.

Stage 13: Side Effects

Declarative secondary operations triggered by the primary command:

{
  "sideEffects": [
    {
      "type": "CREATE",
      "targetModel": "activity_log",
      "fieldMap": {
        "entity_type": "order",
        "entity_id": "${recordId}",
        "action": "STATUS_CHANGED",
        "description": "Order status changed to ${status}"
      }
    }
  ]
}

Side effects run in the same transaction, ensuring atomicity.

Stage 14: Roll-Up Aggregation

If the modified record is a child in a roll-up relationship, the parent's aggregated field is recalculated:

{
  "feature": {
    "rollUp": {
      "childModel": "order_line",
      "childField": "amount",
      "childFk": "order_id",
      "function": "SUM"
    }
  }
}

Supported functions: SUM, COUNT, AVG, MIN, MAX.

Stage 15: Linkage Effects

Frontend form linkage rules are evaluated — cascading dropdowns, conditional visibility, computed displays.

Stage 16: Audit Logging

Every mutation is recorded with the user, timestamp, operation type, changed fields, and previous values. Audit logs are immutable and tenant-scoped.

Stage 17: Cache Invalidation

Related caches are invalidated: model schema cache, named query results, dashboard aggregations, and any custom cache entries.

Stage 18: Event Publishing

An AuraEvent is published to the internal event bus. Listeners can react asynchronously to trigger notifications, webhooks, or downstream processing.

Stage 19: Webhook Dispatch

If configured, the event is dispatched to external webhook URLs with the full payload, supporting retry and dead-letter queuing.

Stage 20: Response

The pipeline returns a structured response with the created/updated record, any validation errors, and metadata.

Customizing the Pipeline

Not every command needs every stage. A simple status update might skip field defaults, computed fields, and confirmation. A complex financial transaction might add custom pre-hooks and additional business validations.

Each stage is enabled or disabled through the command's DSL configuration. No code changes required.

Real-World Example: Order Approval

Consider a purchase order approval workflow. The command DSL might look like:

{
  "code": "purchase_order__submit_for_approval",
  "modelCode": "purchase_order",
  "actionType": "UPDATE",
  "triggerMode": "DIRECT",
  "permissionCode": "procurement:po:submit",
  "businessValidation": {
    "rules": [
      { "field": "status", "operator": "EQ", "value": "DRAFT", "message": "Only draft orders can be submitted" },
      { "field": "total_amount", "operator": "GT", "value": 0, "message": "Order must have line items" }
    ]
  },
  "fieldDefaults": {
    "status": "PENDING_APPROVAL",
    "submitted_at": "${NOW}",
    "submitted_by": "${CURRENT_USER}"
  },
  "sideEffects": [
    {
      "type": "CREATE",
      "targetModel": "approval_task",
      "fieldMap": {
        "entity_type": "purchase_order",
        "entity_id": "${recordId}",
        "approver": "${department_manager}",
        "due_date": "${DATE_ADD(NOW, 3, 'DAY')}"
      }
    }
  ]
}

This single command definition:

  1. Checks the user has procurement:po:submit permission (Stage 3)
  2. Validates the order is in DRAFT status and has items (Stage 7)
  3. Sets status, timestamp, and submitter (Stage 6)
  4. Saves the update (Stage 11)
  5. Creates an approval task for the department manager (Stage 13)
  6. Logs the entire operation for audit (Stage 16)
  7. Publishes an event for notifications (Stage 18)

Seven behaviors, zero lines of imperative code.

Error Handling

If any stage fails, the entire transaction rolls back. The client receives a structured error response indicating which stage failed and why. This makes debugging straightforward — you always know exactly where in the pipeline the problem occurred.

Conclusion

The 20+ stage pipeline is what separates AuraBoot from simple CRUD generators. It provides a shared path for permission checks, validation, auditing, event publishing, and extensions while keeping the behavior configurable through the DSL.

Learn more in our Command System documentation or try building your first command with the quick start guide.