Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Deepen PracticeOrdered learning track

Data Validation, Constraints, Invariants, and State Guard Model

Model validation, constraint, invariant, guard condition, state transition rule, database constraint, domain validation, API validation, async validation, data quality rule, and production correctness for enterprise CPQ/Quote/Order/Billing systems.

10 min read1878 words
PrevNext
Lesson 5082 lesson track46–68 Deepen Practice
#enterprise-data-modelling#validation#constraints#invariants+5 more

Data Validation, Constraints, Invariants, and State Guard Model

1. Core Idea

Data correctness is not achieved by "checking input once".

Enterprise systems need multiple layers of correctness:

  • API validation,
  • command validation,
  • domain invariant,
  • state transition guard,
  • database constraint,
  • uniqueness constraint,
  • foreign key or logical reference validation,
  • async consumer validation,
  • integration contract validation,
  • reconciliation rule,
  • data quality monitor.

Mental model:

Validation rejects bad input. Constraints prevent impossible persistence. Invariants protect business truth. Guards control lifecycle movement. Reconciliation detects what escaped.


2. Why This Model Matters

Without explicit validation/invariant model:

  • quote item created without required configuration,
  • price total mismatches item totals,
  • order completed while item still open,
  • product disconnected without product instance reference,
  • active recurring charge exists for terminated product,
  • duplicate order created from same quote,
  • billing account inactive but order submitted,
  • approval bypassed by status patch,
  • effective-dated records overlap,
  • usage charged twice,
  • downstream event creates invalid local projection.

Production correctness requires layered defense.


3. Validation vs Constraint vs Invariant vs Guard

ConceptMeaning
ValidationCheck data/input before accepting command.
ConstraintPersistence-level rule preventing invalid storage.
InvariantBusiness rule that must always hold.
GuardRule that must pass before state transition/action.
PolicyBusiness-specific decision rule that may change.
ReconciliationDetect mismatch after distributed/async processing.

Example:

Validation:
  quantity must be provided.

Constraint:
  quantity > 0.

Invariant:
  quote total = sum quote item totals.

Guard:
  quote cannot be accepted unless required approvals are approved.

Reconciliation:
  accepted quote should have one converted order.

4. Layered Correctness Model

flowchart TD A["API DTO Validation"] --> B["Command Validation"] B --> C["Domain Invariant Check"] C --> D["State Transition Guard"] D --> E["Database Constraints"] E --> F["Outbox/Event Contract Validation"] F --> G["Consumer Idempotency + Validation"] G --> H["Reconciliation / Data Quality Monitor"]

No single layer is enough.

API validation helps user feedback.

Database constraint protects data even if application has bug.

Reconciliation catches distributed failures.


5. API Validation

API validation checks request shape and basic rules.

Examples:

  • required field present,
  • string length,
  • valid UUID format,
  • valid enum value,
  • positive quantity,
  • valid date format,
  • currency code format,
  • page size limit.

Example DTO validation:

CreateQuoteRequest
- customerId required
- currency required
- items not empty
- item.quantity > 0

API validation should not contain all business logic.

It cannot verify complex lifecycle or cross-service rules alone.


6. Command Validation

Command validation checks whether a business command is well-formed.

Example:

AcceptQuoteCommand
- quoteId required
- expectedVersion required
- acceptedBy required
- acceptanceEvidence required if policy requires
- idempotencyKey required for external channel

Command validation bridges API DTO and domain model.

It should be independent of transport where possible.


7. Domain Invariants

Domain invariants must always hold within aggregate boundary.

Examples:

Quote

Quote total must equal sum of active quote item totals.
Accepted quote must be immutable.
Quote cannot have duplicate active item sequence.

Order

Order item must belong to same order as parent item.
Order cannot be completed while mandatory items are non-terminal.

Product inventory

Active product instance must have valid customer and product offering reference.
Terminated product must have termination date.

Billing

Invoice total must equal line totals plus tax minus discount.
One-time charge must not bill twice for same trigger.

Invariants should be expressed in code and, where feasible, database constraints.


8. State Transition Guards

State transition guard controls lifecycle movement.

Example quote guard:

DRAFT -> PRICED:
  all required configuration valid
  price calculation successful

PRICED -> SUBMITTED:
  no blocking pricing errors
  quote not expired

SUBMITTED -> APPROVED:
  required approval decisions approved

APPROVED -> ACCEPTED:
  approval not invalidated
  quote validUntil not expired

Guards should be centralized. Do not scatter lifecycle if checks across controllers, mappers, and consumers.


9. Database Constraints

Database constraints are last line of defense.

Common constraints:

  • primary key,
  • unique key,
  • not null,
  • check constraint,
  • foreign key,
  • exclusion constraint,
  • partial unique index,
  • generated column constraint.

Examples:

alter table quote_item
add constraint chk_quote_item_quantity_positive
check (quantity > 0);
create unique index uq_order_from_quote_version
on product_order (source_quote_id, source_quote_version)
where source_quote_id is not null;

Database constraints should protect non-negotiable invariants.

Do not depend only on application code for uniqueness/idempotency.


10. Logical References in Microservices

In microservices, foreign keys across databases may not be possible.

Example:

order.billing_account_id references billing account owned by billing service

You cannot enforce DB FK if separate DBs.

Alternatives:

  • validate via API at command time,
  • store reference snapshot,
  • subscribe to account events,
  • maintain local projection,
  • reconcile invalid references,
  • reject if projection stale beyond policy.

Logical reference still needs ownership and validation.


11. Uniqueness and Idempotency Constraints

Uniqueness protects business idempotency.

Examples:

One order per source quote version.
One active billing account number.
One current product characteristic per product/name.
One active recurring charge per subscription item/type/effective period.
One inbox message per event/subscriber.

Use partial unique indexes where needed.

Example:

create unique index uq_current_product_characteristic
on product_instance_characteristic (product_instance_id, characteristic_name)
where effective_to is null;

Be careful if business allows multiple current values.


12. Cross-Field Validation

Many rules involve multiple fields.

Examples:

If action = MODIFY, targetProductInstanceId is required.
If billingStatus = ACTIVATED, billingActivatedAt is required.
If status = TERMINATED, terminationDate is required.
If autoRenew = true, renewalPolicy is required.
If approvalRequired = true, approvalRequestId is required.

Database check example:

alter table product_order_item
add constraint chk_modify_requires_product_instance
check (
  action not in ('MODIFY', 'DISCONNECT', 'SUSPEND', 'RESUME')
  or target_product_instance_id is not null
);

Application must still provide good error messages.


13. Temporal Constraints

Temporal constraints prevent historical ambiguity.

Examples:

  • effective_to > effective_from,
  • effective periods do not overlap,
  • term_end_date >= term_start_date,
  • billing_period_end > billing_period_start,
  • quote valid_until after created_at,
  • cancellation effective date not before activation unless policy allows.

Check constraints handle simple rules.

Overlap often needs application logic, exclusion constraints, or reconciliation.


14. Money Constraints

Financial data needs precision and consistency.

Examples:

  • currency required,
  • amount scale consistent,
  • negative amount allowed only for credit/discount,
  • invoice total equals line totals,
  • discount cannot exceed allowed threshold without approval,
  • margin cannot be below threshold without approval,
  • tax amount cannot be negative unless adjustment.

Some are database constraints. Some are business guards.

Never use floating point for money.


15. Quantity and Unit Constraints

Quantity depends on product.

Examples:

  • quantity must be integer for devices,
  • quantity can be decimal for bandwidth/storage,
  • quantity must equal one for non-quantity product,
  • unit must match meter/product type,
  • usage quantity cannot be negative unless correction event.

This often requires catalog-driven validation.

Fields:

quantity
unit_of_measure
quantity_semantics
quantity_precision

16. Configuration Validation

Product configuration validation checks:

  • required characteristics present,
  • values allowed by characteristic spec,
  • dependencies between characteristics,
  • compatibility with offering,
  • site/serviceability,
  • bundle rules,
  • quantity rules,
  • current product state for modify,
  • catalog version.

Example:

Static IP add-on requires parent internet access product.
Bandwidth must be one of allowed values for offering and site.

Configuration validation should produce structured errors, not one generic invalid config message.


17. Pricing Validation

Pricing validation checks:

  • price list exists,
  • price effective date valid,
  • currency supported,
  • discount allowed,
  • override reason present,
  • approval required if threshold exceeded,
  • total matches item price,
  • tax assumption valid,
  • price snapshot captured.

Pricing rules are business policies, not only math.


18. Billing Readiness Validation

Before billing trigger:

  • billing account active,
  • billing profile complete,
  • billing address valid,
  • tax profile valid,
  • product/service activated,
  • charge snapshot available,
  • duplicate charge absent,
  • effective date valid,
  • no blocking credit hold unless override.

Billing readiness result should be stored if disputes are common.


19. Async Consumer Validation

Event consumers must validate incoming events.

Examples:

  • schema version supported,
  • required fields present,
  • aggregate version monotonic,
  • referenced local projection exists or can be resolved,
  • event not already processed,
  • event state transition allowed,
  • payload not stale.

Do not blindly trust events, especially from external systems.

Use inbox and validation errors.


20. Integration Contract Validation

External payloads should be validated at boundary.

Examples:

  • CRM order request,
  • billing ack,
  • OSS provisioning response,
  • address validation response,
  • usage feed,
  • payment status file.

Store validation errors:

integration_validation_error
- message_id
- source_system
- error_code
- field_path
- raw_value_reference
- detected_at
- status

Do not silently discard malformed external messages.


21. Data Quality Rule Model

Some validations run after the fact.

Data quality rule:

data_quality_rule
- id
- rule_code
- entity_type
- severity
- description
- query_or_check_reference
- owner_group
- active

Data quality result:

data_quality_result
- rule_id
- entity_type
- entity_id
- result
- severity
- detected_at
- resolved_at
- resolution_action

This makes data quality operationally visible.


22. Severity

Validation and data quality issues need severity.

SeverityMeaning
ERRORMust block command/process.
WARNINGAllow but notify/record.
INFONon-blocking observation.
CRITICALProduction incident / financial/customer impact.

Example:

Missing optional billing contact = WARNING
Inactive billing account = ERROR
Duplicate charge = CRITICAL

Do not treat every issue equally.


23. Exception and Override Model

Business may allow override.

Examples:

  • serviceability unknown but manager approves,
  • credit hold overridden by finance,
  • discount threshold approved,
  • backdated billing correction approved,
  • invalid address manually accepted.

Override must store:

override_id
override_type
target_type
target_id
rule_code
approved_by
approval_reference
reason_code
expires_at
created_at

Override is not deletion of validation rule. It is controlled exception.


24. Rule Versioning

Validation rules change.

Examples:

  • new product requires new characteristic,
  • discount threshold changes,
  • serviceability policy changes,
  • billing readiness rule changes.

Store rule version in validation result when important:

validation_rule_version
evaluated_at
evaluated_value

This helps answer:

Why did this quote pass validation at that time?


25. PostgreSQL Physical Design

Validation result:

create table validation_result (
  id uuid primary key,
  target_type text not null,
  target_id uuid not null,
  validation_context text not null,
  status text not null,
  evaluated_at timestamptz not null,
  rule_version text,
  correlation_id text
);

Validation violation:

create table validation_violation (
  id uuid primary key,
  validation_result_id uuid not null references validation_result(id),
  rule_code text not null,
  severity text not null,
  field_path text,
  message text,
  actual_value text,
  expected_value text,
  blocking boolean not null default true
);

Data quality rule/result:

create table data_quality_rule (
  id uuid primary key,
  rule_code text not null unique,
  entity_type text not null,
  severity text not null,
  description text,
  owner_group text,
  active boolean not null default true
);
create table data_quality_result (
  id uuid primary key,
  rule_id uuid not null references data_quality_rule(id),
  entity_type text not null,
  entity_id uuid not null,
  result text not null,
  severity text not null,
  detected_at timestamptz not null,
  resolved_at timestamptz,
  resolution_action text
);

Indexes:

create index idx_validation_target
on validation_result (target_type, target_id, evaluated_at desc);

create index idx_violation_rule_severity
on validation_violation (rule_code, severity);

create index idx_dq_result_open
on data_quality_result (entity_type, severity, detected_at)
where resolved_at is null;

26. Java/JAX-RS Backend Implications

Validation should be layered.

Example:

Resource DTO validation:
  bean validation / request parser

Application service:
  command validation
  permission/authority check
  state guard

Domain service:
  aggregate invariants

Repository:
  unique constraints / DB constraints

Async:
  consumer validation + inbox

Ops:
  reconciliation/data quality job

Pseudo-code:

public Quote acceptQuote(AcceptQuoteCommand command) {
    commandValidator.validate(command);

    Quote quote = quoteRepository.load(command.quoteId());

    authorizationService.assertAllowed(command.actor(), ACCEPT_QUOTE, quote);
    quoteStateGuard.assertCanAccept(quote);
    approvalGuard.assertApprovalsValid(quote);
    invariantChecker.assertQuoteTotalsValid(quote);

    quote.accept(command.actor());

    quoteRepository.save(quote);
    outbox.append(QuoteAcceptedEvent.from(quote));
    audit.append(...);

    return quote;
}

27. Bean Validation Is Not Enough

Java Bean Validation can check:

@NotNull
@Size
@Positive

It cannot fully enforce:

  • quote lifecycle,
  • customer/account eligibility,
  • serviceability,
  • approval authority,
  • cross-item bundle rules,
  • database uniqueness,
  • distributed idempotency,
  • billing readiness,
  • event consumer idempotency.

Use Bean Validation for boundary shape, not full domain correctness.


28. Error Model

Validation errors should map to stable error codes.

Example:

{
  "errorCode": "VALIDATION_FAILED",
  "violations": [
    {
      "ruleCode": "BILLING_ACCOUNT_ACTIVE_REQUIRED",
      "field": "billingAccountId",
      "severity": "ERROR",
      "message": "Billing account must be active"
    }
  ],
  "correlationId": "corr-123"
}

For internal logs/audit, store rule code and target.

Do not rely only on free-text messages.


29. Observability

Monitor:

  • validation failure rate,
  • top rule violations,
  • data quality open issues,
  • critical data quality breaches,
  • override usage,
  • DB constraint violations,
  • event validation failures,
  • integration validation failures,
  • reconciliation mismatch trend.

Example queries:

-- Top validation violations
select rule_code, severity, count(*)
from validation_violation
group by rule_code, severity
order by count(*) desc;

-- Open critical data quality issues
select dqr.rule_code, r.entity_type, r.entity_id, r.detected_at
from data_quality_result r
join data_quality_rule dqr on dqr.id = r.rule_id
where r.resolved_at is null
  and r.severity = 'CRITICAL';

-- Overrides expiring soon
select id, override_type, target_type, target_id, expires_at
from validation_override
where expires_at between now() and now() + interval '7 days';

30. Failure Modes

Failure modeSymptomLikely causePrevention
Invalid order stateOrder completed with open itemsMissing state guardHeader/item invariant
Duplicate orderSame quote converted twiceNo uniqueness/idempotencyUnique source quote/version
Bad product configFulfillment failsWeak configuration validationCatalog-driven validation
Wrong billing accountBilling rejectedNo billing readiness validationBilling account guard
Duplicate chargeCustomer billed twiceRetry without DB uniquenessIdempotency constraint
Temporal overlapDouble billingNo effective period validationNon-overlap rule
Approval bypassDiscount accepted unapprovedGeneric status updateApproval guard
Event corrupts projectionConsumer accepts invalid eventNo consumer validationSchema/version/state check
Data quality invisibleBad records accumulateNo DQ result modelDQ rules and dashboard
Override abuseRule bypass becomes normalNo expiry/auditControlled override model

31. PR Review Checklist

When reviewing data-changing code, ask:

  • What validation layer handles this?
  • What invariant must always hold?
  • Is there a database constraint for non-negotiable rule?
  • Is uniqueness/idempotency enforced by DB?
  • Is lifecycle transition guarded?
  • Are cross-field rules checked?
  • Are temporal overlaps prevented?
  • Are money/currency rules enforced?
  • Is configuration/catalog validation involved?
  • Is billing readiness validated?
  • Are async consumers validating events?
  • Are validation errors structured?
  • Are overrides allowed and audited?
  • Are data quality/reconciliation checks needed?
  • Are tests covering invalid state and concurrency?

32. Internal Verification Checklist

Verify these in the internal CSG/team context:

  • Standard validation framework and error response model.
  • Where domain invariants are implemented.
  • Whether lifecycle guards are centralized.
  • Whether database constraints exist for uniqueness/idempotency.
  • Whether quote total/item total consistency is checked.
  • Whether order header/item state consistency is checked.
  • Whether billing readiness validation exists.
  • Whether serviceability/configuration validation exists.
  • Whether approval guard is enforced server-side.
  • Whether event consumer validation exists.
  • Whether integration validation errors are persisted.
  • Whether data quality rules/results are monitored.
  • Whether override/exception model exists.
  • Whether incidents mention invalid state, duplicate charge/order, missing validation, or bad data escaping into billing/fulfillment.

33. Summary

Validation is only one layer of correctness.

A strong enterprise model must define:

  • API validation,
  • command validation,
  • domain invariants,
  • state guards,
  • database constraints,
  • uniqueness/idempotency constraints,
  • temporal constraints,
  • money/quantity/configuration validation,
  • async consumer validation,
  • integration validation,
  • data quality rules,
  • override model,
  • reconciliation checks.

The key principle:

Trust no single layer. Production correctness comes from layered validation, enforced invariants, database constraints, idempotency, and continuous reconciliation.

Lesson Recap

You just completed lesson 50 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.