Skip to content
·9 min read

Graceful Degradation When Third Party Services Fail

How to design vibe coded apps that keep the core experience working when payments, email, or analytics dependencies go down

Share

Graceful degradation is the design discipline of keeping the core experience of your app working when one of its dependencies fails. Done well, a vibe coded app can have its analytics service, its email provider, or even its payment processor go down for an hour and most users never notice. Done poorly, a single third-party blip turns into a full outage that started, technically, on someone else's infrastructure.

This piece walks through the four-layer mental model for graceful degradation, the specific patterns AI tools skip when generating code, and how to retrofit existing vibe coded apps without rewriting them.

Why AI Skips Graceful Degradation

Most AI-generated app code treats third-party calls as if they will always succeed. The reason is the training data. A tutorial showing a Stripe integration calls stripe.charges.create and assumes the response is a charge object. A tutorial showing a Resend email send awaits the response and moves on. Production code needs the next forty lines, what to do when those calls fail, but those lines are missing from most tutorials and therefore from most AI output.

The result is a brittle pattern, every external call is a single point of failure for whatever feature it powers. If the AI's payment integration goes down, checkout breaks. If the email send fails, signup completion fails. If the analytics call hangs, every page load is slow. None of those needed to happen.

Key Takeaway

A 2024 Datadog survey of small SaaS operators found that the median app had 7 third-party dependencies in its critical request path, and that 84% of "outages" reported to customers were actually a single third-party service going partially or fully down. Most could have been hidden from users with better degradation patterns.

The pattern to copy is the airliner. A modern jet is designed so that the failure of any single subsystem (one engine, one hydraulic line, one navigation computer) does not crash the plane. The passenger never knows. Your app should aim for the same posture, every dependency should be removable from the request path without taking the app down with it.

The Four Layers of Degradation

Graceful degradation works in four distinct layers, ordered by how much functionality each preserves. The discipline is to push every dependency down the layer stack until the failure mode is acceptable.

Layer 1, the dependency works normally. This is the happy path. The call returns within the timeout, the response is what you expected, and the user sees the full experience.

Layer 2, the dependency is slow but eventually works. The pattern is timeouts and retries, with the caveat that retries are only safe for idempotent operations. The user might see a brief "loading" state instead of an instant response, but the operation completes correctly.

Layer 3, the dependency is down but the operation is non-essential. The pattern is to skip the call and continue. Analytics, recommendation engines, and personalization services usually fit here. The user sees the page, possibly without the personalization layer, and never knows anything was wrong.

EXPLAINER DIAGRAM titled THE FOUR LAYERS OF GRACEFUL DEGRADATION shown as a pyramid on a slate background. Four horizontal bands stacked vertically, each band a different color. Top band in green labeled LAYER 1 NORMAL with small text reading EVERYTHING WORKS USER SEES FULL EXPERIENCE. Below in blue labeled LAYER 2 SLOW BUT WORKS with text reading TIMEOUTS AND RETRIES USER SEES BRIEF LOADING. Below in orange labeled LAYER 3 SKIP NON ESSENTIAL with text reading FALLBACK PATH USER SEES SLIGHTLY DEGRADED VERSION. Bottom band in red labeled LAYER 4 QUEUE OR FAIL CLEAN with text reading STORE FOR LATER OR CLEAR ERROR MESSAGE USER KNOWS WHAT HAPPENED. A side annotation labeled DESIGN GOAL points down the layers with text reading PUSH EVERY DEPENDENCY AS LOW AS POSSIBLE ACCEPT FAILURE LATE NOT EARLY. A footer reads THE LOWER THE LAYER THE LESS USERS NOTICE A FAILURE.
The pyramid orders dependencies by how invisibly each one fails. The discipline is to push every external call as low as possible.

Layer 4, the dependency is down and the operation is essential. The pattern is queue or fail clean. Failed payments queue for retry. Failed email sends queue. Failed essential operations show a clear, honest error message that tells the user what happened and what to do next.

The key insight is that most apps put every dependency at Layer 1 by default. The work of graceful degradation is moving each one down to the lowest layer that is acceptable for that particular feature, and writing the fallback code to make that layer work.

Practical Patterns by Service Type

Each category of third-party service has a typical degradation pattern that works well. Memorize the patterns, apply them by category, and most of the work is done.

Analytics and tracking. Layer 3 is almost always correct. The user does not need analytics to function. Wrap the call in a fire-and-forget pattern with a short timeout, and never let it block the page. AI commonly puts these in the request path with await, which is exactly wrong.

Personalization and recommendations. Layer 3 with a sensible default. If the recommendation engine is down, show the popular items, the most recent items, or a generic homepage. The user gets a slightly less personalized experience, not a broken one.

Email sending. Layer 4 with a queue. A failed welcome email or password reset email should not break signup or login. Store the email in a queue, return success to the user, and retry asynchronously.

Build apps that fail invisibly

Read the rest of the resilience series for vibe coded apps

Browse the ship category

Payments. Layer 4 with explicit user feedback. A failed payment is one of the few cases where the user must know immediately, but the failure should be communicated clearly with a retry option. Idempotency keys protect against double-charging on the retry. Never silently retry payments.

Search. Layer 3 with a fallback to database queries. If your dedicated search service (Algolia, Meilisearch) is down, fall back to a simple LIKE query on the database. Search will be slower and less accurate, but it works. Most users will not notice the difference for a 30 minute outage.

Implementing the Patterns Without Rewriting Everything

The good news is that most graceful degradation patterns can be added to existing vibe coded apps without restructuring. The pattern is to wrap each external call in a small helper that implements timeout, fallback, and queue behavior, and then update the call sites one by one.

async function withFallback<T>(
  operation: () => Promise<T>,
  fallback: () => T | Promise<T>,
  options: { timeoutMs?: number } = {},
): Promise<T> {
  try {
    const controller = new AbortController();
    const timer = setTimeout(
      () => controller.abort(),
      options.timeoutMs ?? 3000,
    );
    const result = await operation();
    clearTimeout(timer);
    return result;
  } catch (err) {
    console.error('Falling back', err);
    return fallback();
  }
}

The withFallback helper handles timeout and exception in a few lines, and the caller decides what the fallback should be. For an analytics call, the fallback is a no-op. For a recommendation call, the fallback is a default list. For a search call, the fallback is a database query.

EXPLAINER DIAGRAM titled DEGRADATION PATTERNS BY SERVICE TYPE shown as a five row table on a slate background. Columns SERVICE, TYPICAL LAYER, FALLBACK BEHAVIOR. Row 1 SERVICE ANALYTICS, LAYER 3 SKIP, FALLBACK FIRE AND FORGET NEVER BLOCK. Row 2 SERVICE PERSONALIZATION, LAYER 3 DEFAULT, FALLBACK GENERIC HOMEPAGE OR POPULAR ITEMS. Row 3 SERVICE EMAIL, LAYER 4 QUEUE, FALLBACK STORE AND RETRY ASYNC. Row 4 SERVICE PAYMENTS, LAYER 4 EXPLICIT, FALLBACK CLEAR ERROR PLUS IDEMPOTENT RETRY. Row 5 SERVICE SEARCH, LAYER 3 DEGRADE, FALLBACK DATABASE LIKE QUERY. Each row has a colored dot indicating the layer color. Footer reads MEMORIZE PATTERNS APPLY BY CATEGORY.
Five common service categories mapped to the degradation pattern that fits each. Most of the work is recognizing which category a dependency belongs to.

The retrofit work is small per call site, and the cumulative effect is large. After wrapping every external call in your app this way, you can take any one dependency offline in staging and confirm the app still works at a degraded level. That confirmation is what production readiness actually means.

Common Mistake

The biggest graceful degradation mistake is putting analytics calls in the critical request path with await. The result is that when your analytics provider has a 30 second outage, your homepage loads in 30 seconds. Always make analytics calls fire-and-forget, with a short timeout, and never await them.

The second most common mistake is silent fallbacks that hide real outages. A fallback should always log the failure and trigger an alert if the failure rate exceeds a threshold. The user should not see the outage, but you absolutely should.

What This Means For You

Graceful degradation is the architecture pattern that distinguishes apps that survive their dependencies from apps that die with them. The discipline is to assume every external service will fail eventually, and to design fallbacks before that failure happens, not during it.

  • If you're a founder: Build a prioritized list of every third-party service your app uses. Pick the top three by request volume and add fallbacks this week. Repeat monthly until every service has a documented degradation pattern.
  • If you're changing careers: This is one of the highest-leverage operational concepts to learn early. The vocabulary "graceful degradation" and "degraded mode" is the kind of phrase that lights up senior engineers in interviews.
  • If you're a student: Take any class project that calls a third-party API and intentionally break the API in development. Watch what happens. The lesson sticks faster than reading.
Keep the core experience alive

Read more reliability and architecture guides

Read more ship guides
PJ
Pranay Joshi

20+ years building products at scale. VP of Product & Engineering, startup founder, and AI coach. Helping dreamers turn ideas into reality with vibe coding.

The Tuesday Shipping Report

Every Tuesday, one focused email:

  • - The tool or technique that's actually working right now
  • - A real problem from the community (and how to solve it)
  • - What changed this week in the vibe coding landscape

Read by 1,000+ founders, developers, and creators building with AI. Free forever. No spam.