✦ For everyone, free.

Practical knowledge for real and everyday life

Home

9.3.3.5 App Retry Responsibility

A focused guide to App Retry Responsibility, connecting core concepts with practical Docker and container operations.

App retry responsibility refers to the application-level code that handles connection failures and retries for its own dependencies, an essential complement to Compose's startup-time depends_on coordination, since that coordination alone cannot address every scenario where a dependency is temporarily unavailable.

Why This Responsibility Falls to the Application, Not Compose

Compose's depends_on mechanism addresses startup sequencing — it has no ongoing role once services are running, meaning any later, transient unavailability of a dependency is a scenario the application itself needs to handle through its own logic.

import time

def connect_with_retry(max_attempts=5, delay=2):
    for attempt in range(max_attempts):
        try:
            return connect_to_database()
        except ConnectionError:
            if attempt == max_attempts - 1:
                raise
            time.sleep(delay)
Designing Retry Logic With Appropriate Backoff

Retrying immediately and repeatedly against a still-unavailable dependency can itself contribute to an ongoing problem — incorporating a backoff strategy, where the delay between attempts grows, is generally a more considerate approach.

def connect_with_backoff(max_attempts=5):
    delay = 1
    for attempt in range(max_attempts):
        try:
            return connect_to_database()
        except ConnectionError:
            if attempt == max_attempts - 1:
                raise
            time.sleep(delay)
            delay *= 2
Handling Both Initial Connection and Ongoing Reconnection

Retry logic is valuable not just for an application's initial startup connection attempt, but also for gracefully reconnecting if an established connection is lost at some later point during normal operation.

def get_connection():
    global _connection
    if _connection is None or _connection.closed:
        _connection = connect_with_backoff()
    return _connection
Why App Retry Responsibility Matters

Building reasonable retry and reconnection logic directly into an application is essential resilience that Compose's own startup coordination cannot provide on its own, ensuring an application can gracefully handle both its initial startup sequencing and any later, transient unavailability of its dependencies.