Skip to navigation

Service Bus Message Error Classification Strategy

Spike: Error Classification Design (User Story 762531)

1. Summary

This document defines a standardized error classification strategy for Azure Service Bus message processing across Fluxx microservices. The strategy distinguishes between transient failures (temporary, retriable) and permanent failures (non-retriable) to optimize system reliability and operational efficiency.

Key Outcomes

  • Clear taxonomy of message processing errors
  • Decision rules for retry vs dead-letter actions
  • Improved system reliability and reduced operational noise
  • Ensure the approach is consistent, configurable, observable, debuggable, and testable.

2. Problem Statement

Current State

Currently in fluxx-extractor (and likely other services):

  • All message processing errors are treated the same way
  • Failed messages are always abandoned for retry, regardless of error type
  • No distinction between transient (network timeout) vs permanent (invalid data) failures
  • Validation errors retry indefinitely until max delivery count
  • Dead-letter queues contain mix of retriable and non-retriable messages
  • Limited error metadata makes troubleshooting difficult

Impact

  • Wasted Service Bus resources on non-retriable errors
  • Delayed identification of systematic issues (e.g., missing configuration)
  • Poor operational visibility into failure reasons
  • Inconsistent behavior across microservices

Design Goals

Primary Goals

  1. Clear Error Taxonomy - Establish standardized categories for all message processing failures
  2. Intelligent Retry Logic - Apply conditional retry based on error classification
  3. Operational Correctness - Dead-letter permanent failures immediately, retry transient failures
  4. Cross-Service Consistency - Same approach in all Fluxx microservices
  5. Enhanced Observability - Rich metadata and structured logging for debugging

3. Error Classification Framework

3.1 Classification Principles

Transient Errors

Errors that are temporary and likely to succeed on retry without any code or data changes.

Characteristics:

  • External dependency temporarily unavailable
  • Network connectivity issues
  • Resource contention that resolves over time
  • Rate limiting that expires

Strategy: Retry with exponential backoff

Permanent Errors

Errors that will never succeed regardless of retries without intervention.

Characteristics:

  • Invalid input data
  • Missing configuration
  • Business rule violations
  • Resources that don’t exist

Strategy: Immediate dead-letter for manual investigation


4. Error Taxonomy

4.1 Transient Error Categories

TRANSIENT_SERVICE

External service temporarily unavailable

AttributeValue
RetryableYes
Max Retries10 attempts
Retry DelayService Bus default (lock duration)
HTTP Status Codes500, 502, 503, 504
Common Causes- Service deployment in progress
- Temporary outage
- Circuit breaker open
- Service restarting
ResolutionAutomatic - wait for service recovery
ExampleRegistration API returns 503 during deployment

Rationale: Services typically recover within minutes. Retry allows automatic recovery without manual intervention.


TRANSIENT_NETWORK

Network connectivity issues

AttributeValue
RetryableYes
Max Retries10 attempts
Error CodesECONNREFUSED, ETIMEDOUT, ENOTFOUND, ENETUNREACH, ECONNRESET
Common Causes- DNS resolution failure
- Network partition
- Firewall blocking
- Service not listening
ResolutionAutomatic - network typically recovers
ExampleConnection refused when calling external API

Rationale: Network issues are often transient. DNS, routing, and firewall issues typically resolve quickly.


TRANSIENT_THROTTLING

Rate limiting by external service

AttributeValue
RetryableYes
Max Retries10 attempts
Retry StrategyHonor Retry-After header if present
HTTP Status Codes429
Common Causes- API quota exceeded
- Too many requests per second
- Burst limit exceeded
ResolutionAutomatic - wait for quota reset
ExampleDocument AI API returns 429 with Retry-After: 60

Rationale: Rate limits typically reset automatically. Respecting Retry-After prevents additional throttling.

Future Enhancement: Implement exponential backoff or circuit breaker pattern.


TRANSIENT_RESOURCE

Resource contention that resolves over time

AttributeValue
RetryableYes
Max Retries10 attempts
Common Causes- Database deadlock
- Lock timeout
- Service Bus message lock lost
- Connection pool exhausted
ResolutionAutomatic - contention resolves as resources free up
ExampleDatabase deadlock during concurrent job updates

Rationale: Resource contention is temporary by nature. Deadlocks resolve automatically, and pools refill.


4.2 Permanent Error Categories

PERMANENT_VALIDATION

Invalid message data or structure

AttributeValue
RetryableNo
ActionImmediate dead-letter
HTTP Status Codes400
Common Causes- Missing required fields
- Invalid data format
- Type mismatch
- Schema validation failure
ResolutionManual - fix data source, update message, resubmit
ExampleMessage missing applicationId field

Rationale: Invalid data will never become valid through retry. Immediate dead-lettering allows quick identification and fix.

Dead-Letter Metadata:

{
"deadLetterReason": "PERMANENT_VALIDATION",
"deadLetterErrorDescription": "[Attempt 1] Missing required field: applicationId",
"originalMessage": { /* message body */ }
}

PERMANENT_CONFIGURATION

Missing or invalid configuration

AttributeValue
RetryableNo
ActionImmediate dead-letter
Common Causes- No extractors configured
- Missing environment variables
- Invalid configuration values
ResolutionManual - update configuration, resubmit message
ExampleNo extractors configured for applicationId

Rationale: Configuration issues require deployment or database changes. Retry wastes resources and delays detection.

Operational Response:

  1. Alert: Page on-call immediately (high severity)
  2. Investigate: Check configuration in database/environment
  3. Fix: Add missing configuration
  4. Reprocess: Resubmit dead-lettered messages

PERMANENT_NOT_FOUND

Resource doesn’t exist

AttributeValue
RetryableNo
ActionImmediate dead-letter
HTTP Status Codes404
Common Causes- Application ID doesn’t exist
- File deleted from blob storage
- Extractor removed
- Stale reference
ResolutionManual - create resource or discard obsolete message
ExampleRegistration API returns 404 for applicationId

Rationale: Resources don’t spontaneously appear. Retry wastes resources checking for non-existent entities.

Decision Tree:

404 Error
↓
Is resource expected to exist?
↓
YES → Create resource → Resubmit
↓
NO → Discard message (obsolete data)

PERMANENT_AUTHORIZATION

Authentication or permission failure

AttributeValue
RetryableNo
ActionImmediate dead-letter
HTTP Status Codes401, 403
Common Causes- Invalid API key
- Expired token
- Insufficient permissions
- Certificate expired
ResolutionManual - update credentials, grant permissions
ExampleExternal API returns 401 with invalid API key

Rationale: Credentials don’t fix themselves. Immediate dead-lettering highlights security/access issues.

Security Consideration: Don’t log credentials in error metadata.


PERMANENT_BUSINESS_RULE

Business logic prevents processing

AttributeValue
RetryableNo
ActionImmediate dead-letter
HTTP Status Codes409
Common Causes- Duplicate entry
- Invalid state transition
- Constraint violation
- Business invariant broken
ResolutionManual - investigate business logic, fix state, decide on reprocess
ExampleAttempting to reprocess already-completed job

Rationale: Business rules are deterministic. Retry won’t change the outcome without state changes.


PERMANENT_MALFORMED

Message structure invalid

AttributeValue
RetryableNo
ActionImmediate dead-letter
Common Causes- Missing message body
- Unparseable JSON
- Corrupted message
- Wrong message type
ResolutionManual - investigate producer, fix serialization, discard corrupt messages
ExampleService Bus message with null body

Rationale: Malformed messages indicate producer bugs. Retry wastes lock time on unparseable data.


5. HTTP Status Code Mapping

5.1 Complete Status Code Classification

Status CodeCategoryRetryableRationale
2xx Success-N/ANo error
400 Bad RequestPERMANENT_VALIDATIONClient error - data invalid
401 UnauthorizedPERMANENT_AUTHORIZATIONInvalid credentials
403 ForbiddenPERMANENT_AUTHORIZATIONInsufficient permissions
404 Not FoundPERMANENT_NOT_FOUNDResource doesn’t exist
405 Method Not AllowedPERMANENT_VALIDATIONWrong HTTP method
408 Request TimeoutTRANSIENT_TIMEOUTNetwork/server slow
409 ConflictPERMANENT_BUSINESS_RULEBusiness constraint
410 GonePERMANENT_NOT_FOUNDResource permanently deleted
422 Unprocessable EntityPERMANENT_VALIDATIONSemantic validation failure
429 Too Many RequestsTRANSIENT_THROTTLINGRate limited
500 Internal Server ErrorTRANSIENT_SERVICEServer error
502 Bad GatewayTRANSIENT_SERVICEUpstream issue
503 Service UnavailableTRANSIENT_SERVICETemporarily down
504 Gateway TimeoutTRANSIENT_SERVICEUpstream timeout

5.2 Edge Cases

408 Request Timeout

Classification: TRANSIENT_TIMEOUT Retryable

Rationale: Despite being 4xx, this indicates network/server performance issue rather than client error.

429 Too Many Requests

Classification: TRANSIENT_THROTTLING Retryable

Special Handling: Check for Retry-After header and respect the delay.

409 Conflict

Classification: PERMANENT_BUSINESS_RULE Not retryable

Rationale: Conflicts require state changes or business logic investigation. Automatic retry won’t resolve.


6. Network Error Code Mapping

6.1 Node.js Error Codes

Error CodeCategoryRetryableDescriptionTypical Cause
ECONNREFUSEDTRANSIENT_NETWORKConnection refusedService not listening on port
ETIMEDOUTTRANSIENT_NETWORKConnection timeoutNetwork slow or service unresponsive
ENOTFOUNDTRANSIENT_NETWORKDNS lookup failedDNS issue or hostname typo
ENETUNREACHTRANSIENT_NETWORKNetwork unreachableRouting issue or network down
ECONNRESETTRANSIENT_NETWORKConnection resetServer dropped connection
ECONNABORTEDTRANSIENT_NETWORKConnection abortedClient/server terminated connection
EHOSTUNREACHTRANSIENT_NETWORKHost unreachableFirewall or routing issue
EPIPETRANSIENT_NETWORKBroken pipeConnection closed unexpectedly
EAI_AGAINTRANSIENT_NETWORKDNS temporary failureDNS server issue

Note: All network errors are considered transient unless they persist beyond max retries.


7. Database Error Classification

7.1 SQL Error Patterns

Error PatternCategoryRetryableExample Message
DeadlockTRANSIENT_RESOURCE”Transaction deadlock detected”
TimeoutTRANSIENT_RESOURCE”Lock wait timeout exceeded”
ConnectionTRANSIENT_NETWORK”Connection refused”, “Cannot connect”
ConstraintPERMANENT_VALIDATION”Duplicate key”, “Foreign key constraint”
SyntaxPERMANENT_VALIDATION”Syntax error in SQL”
PermissionPERMANENT_AUTHORIZATION”Access denied for user”

8. Service Bus Error Classification

8.1 Service Bus Specific Errors

ErrorCategoryRetryableDescriptionAction
MessageLockLostErrorTRANSIENT_RESOURCELock expiredMessage auto-released, will retry
SessionLockLostErrorTRANSIENT_RESOURCESession lock expiredSession will be reacquired
MessagingEntityNotFoundErrorPERMANENT_CONFIGURATIONQueue/topic doesn’t existFix configuration
QuotaExceededExceptionTRANSIENT_RESOURCEService Bus quota exceededWait for quota reset
MessageSizeExceededExceptionPERMANENT_VALIDATIONMessage too largeReduce message size or split

9. Decision Matrix

9.1 Retry Decision Table

This comprehensive table shows exactly how the system decides whether to retry or dead-letter a message based on error characteristics.

Error TypeIs MessageProcessingError?Is Retryable?Delivery CountHTTP StatusError CodeActionRationale
Permanent ValidationYesNoAny400, 422-DEAD_LETTERInvalid data will never become valid
Permanent ConfigurationYesNoAny--DEAD_LETTERRequires manual config update
Permanent Not FoundYesNoAny404, 410-DEAD_LETTERResource doesn’t exist
Permanent AuthorizationYesNoAny401, 403-DEAD_LETTERInvalid credentials/permissions
Permanent Business RuleYesNoAny409-DEAD_LETTERBusiness constraint violation
Permanent MalformedYesNoAny--DEAD_LETTERMessage structure invalid
Transient ServiceYesYes< 10500, 502, 503, 504-RETRYService may recover
Transient ServiceYesYes≥ 10500, 502, 503, 504-DEAD_LETTERExceeded max attempts
Transient NetworkYesYes< 10-ECONNREFUSED, ETIMEDOUTRETRYNetwork may recover
Transient NetworkYesYes≥ 10-ECONNREFUSED, ETIMEDOUTDEAD_LETTERExceeded max attempts
Transient ThrottlingYesYes< 10429-RETRYRate limit will reset
Transient ThrottlingYesYes≥ 10429-DEAD_LETTERExceeded max attempts
Transient ResourceYesYes< 10-DeadlockRETRYContention will resolve
Transient ResourceYesYes≥ 10-DeadlockDEAD_LETTERExceeded max attempts
Unclassified HTTP 5xxNoN/A< 10500, 502, 503, 504-RETRYTreat as transient
Unclassified HTTP 5xxNoN/A≥ 10500, 502, 503, 504-DEAD_LETTERExceeded max attempts
Unclassified HTTP 4xxNoN/AAny400, 401, 403, 404-DEAD_LETTERTreat as permanent
Unclassified NetworkNoN/A< 10-ECONNREFUSED, etc.RETRYTreat as transient
Unclassified NetworkNoN/A≥ 10-ECONNREFUSED, etc.DEAD_LETTERExceeded max attempts
Unclassified UnknownNoN/A< 10--RETRYConservative approach
Unclassified UnknownNoN/A≥ 10--DEAD_LETTERExceeded max attempts

9.2 Quick Reference Decision Tree

Use PERMANENT errors when retry will NEVER succeed 

without manual intervention (code, config, or data change)

PERMANENT_VALIDATION

  • Missing required fields

  • Invalid data format (email, date, etc.)

  • Wrong data type (string vs number)

  • Value out of acceptable range

  • Schema validation failure

  • HTTP: 400 (Bad Request), 422 (Unprocessable Entity)

PERMANENT_CONFIGURATION

  • No extractors configured

  • Missing environment variable

  • Invalid connection string

  • Feature flag disabled

  • Service misconfigured

PERMANENT_NOT_FOUND

  • Application doesn’t exist

  • File deleted from storage

  • Extractor ID invalid

  • Stale reference to removed entity

  • HTTP: 404 (Not Found), 410 (Gone)

PERMANENT_AUTHORIZATION

  • Invalid API key

  • Expired access token

  • Insufficient permissions

  • Certificate expired

  • Service account disabled

  • HTTP: 401 (Unauthorized), 403 (Forbidden)

PERMANENT_BUSINESS_RULE

  • Duplicate operation attempt

  • Invalid state transition

  • Workflow already completed

  • Business constraint violation

  • HTTP: 409 (Conflict)

PERMANENT_MALFORMED

  • Message body is null/undefined

  • Unparseable JSON

  • Corrupted message data

  • Wrong message type on queue

  • Encoding issues


10. Configuration Parameters

ParameterValueRationale
maxDeliveryCount10Balances retry opportunity vs resource waste
lockDuration5 minutesSufficient for typical processing, prevents excessive locking
defaultMessageTTL7 daysAllows reasonable time for manual DLQ processing
enableDeadLetteringOnExpirationtruePreserve expired messages for investigation
treatUnknownAsTransientfalseConservative approach - dead-letter for investigation

10.2 Service Bus Subscription Configuration

subscription:
name: "extractor-accepted-file"
maxDeliveryCount: 10
lockDuration: "PT5M" # ISO 8601: 5 minutes
defaultMessageTimeToLive: "P7D" # ISO 8601: 7 days
deadLetteringOnMessageExpiration: true
enableBatchedOperations: true
maxSizeInMegabytes: 1024

11. Observability Strategy

11.1 Structured Logging Schema

{
"timestamp": "ISO 8601",
"level": "error|warn|info",
"msg": "Human-readable message",
"messageId": "Service Bus message ID",
"source": "Topic name",
"subscription": "Subscription name",
"deliveryCount": 1,
"category": "ERROR_CATEGORY",
"retryable": true|false,
"action": "RETRY|DEAD_LETTER",
"error": "Error message",
"metadata": {
"applicationId": "...",
"fileId": "...",
"status": 500,
"url": "..."
}
}

11.2 Log Levels by Category

CategoryLog LevelRationale
TRANSIENT_*warnExpected transient failures
PERMANENT_*errorUnexpected issues requiring investigation
UNCLASSIFIEDerrorUnknown errors need investigation
Successful retryinfoAudit trail

12. Open Questions

#QuestionOptionsRecommendation
1Should we retry unclassified errors?A) Yes (conservative)
B) No (strict)
A - Be conservative until we understand error patterns
2Max delivery count?A) 5
B) 10
C) 20
B - 10 attempts balances reliability vs resource usage
3Should PERMANENT_NOT_FOUND always dead-letter?A) Yes
B) Retry 1-2 times (eventual consistency)
A - 404s rarely resolve themselves in our architecture
4Log sensitive data in metadata?A) Yes (full context)
B) No (sanitize)
B - Sanitize PII, credentials
5Implement exponential backoff for throttling?A) Phase 1
B) Phase 2
B - Keep simple for initial release

References

1. Azure Service Bus Documentation

2. Industry Standards