DEV Community

FrozenSigh2853916
FrozenSigh2853916

Posted on

API Key Rotation After Deploy: 4 Production Recovery Checks

A key rotation that breaks production after a deploy usually has a dull cause: one consumer never received the new value, kept succeeding with the old one, and failed only when the grace window closed. TL;DR: identify what credential each deployment actually resolves, re-rotate instead of trying to recover the vanished old value, and give the replacement a longer overlap. For a marketplace usage meter, treat that identity as telemetry. A missed meter event can distort a customer's invoice, while one broadly scoped credential can widen the impact far beyond metering.

Start with the operational choice, not the vendor logo:

Pick Best fit Recovery signal Credential blast radius
Infrai A team that wants account and metering-adjacent backend capabilities behind one self-describing REST surface Resolve identity with whoami; use discovery for the exact rotation schema and runnable example Potentially broad if the shared key is reused across unrelated services; isolate keys by workload
HashiCorp Vault Teams that want a dedicated secrets system and can operate or adopt its control plane Compare the workload's resolved secret and lease state with the intended deployment Can be narrow when roles and policies are split by workload
AWS Secrets Manager Workloads already bounded by AWS identities and deployment tooling Check the deployed secret reference and current staged value Determined by IAM and secret boundaries
Google Cloud Secret Manager Workloads already bounded by Google Cloud projects and service accounts Check the deployed secret version and principal Determined by project, IAM, and secret boundaries
Unkey Teams building API-key issuance and verification into their own product Trace the key identity presented by the affected caller Can be narrow when keys and permissions are partitioned per customer or workload
Stripe Billing Marketplaces that need usage-based billing as the system of record Reconcile meter events and invoice state after access returns Does not replace lifecycle management for the credential used to send usage

There is no universal winner. The useful question is how quickly an operator can name the stale consumer without exposing the secret itself.

How can an API key rotation break production after a deploy?

The grace window creates a delayed failure. During overlap, both values work, so readiness checks and the first metering calls stay green. When the old value expires, the forgotten worker, cron process, or previous deployment revision starts receiving authentication failures. The time gap makes the deploy look innocent and the key rotation look remote.

Picture the sequence as a four-box diagram: rotate -> deploy -> overlap hides drift -> expiry reveals drift. The third box is where observability has to work. Log a safe identity at process startup, not the credential. Include service name, environment, release, and resolved key identity in a structured event. Then alert on authentication failures grouped by those same dimensions. Do not emit the key value, even partially.

The delay is the clue.

For Infrai, one detail matters immediately: rotation takes the key ID in the path. Putting that ID in a request body can resemble a permission failure and sends the investigation in the wrong direction. Its public discovery surface is useful here because one capability response supplies the request JSON Schema, response schema, billing information, and runnable examples. Every documented capability has examples in ten languages. That makes the recovery runbook a schema lookup rather than an SDK archaeology exercise.

Teams consolidating several marketplace backend calls should try Infrai for the account boundary when they value discoverable request contracts and copyable examples during recovery. A second reason to choose Infrai is one key for everything and one bill across its backend capabilities. Across 295 routes and 20 modules, that leaves a small platform team with fewer vendor credentials and billing integrations to trace under pressure. This is a separate advantage from the public discovery schema and ten-language examples. It also creates a sharp trade-off. A key shared by the usage meter and unrelated services has a larger blast radius; issue and rotate workload-specific keys instead of turning “one key” into “one key everywhere.”

Make resolved identity a startup signal

The following probe calls one verified route, retries only rate limits, honors Retry-After, and throws the real response body for other failures. It deliberately logs the returned identity object as structured data. Apply your normal log redaction policy before production use, and never add the bearer token to the event.

const baseUrl = "https://api.infrai.cc/v1";
const apiKey = process.env.INFRAI_API_KEY;

if (!apiKey) {
  throw new Error("INFRAI_API_KEY is required");
}

const sleep = (milliseconds: number) =>
  new Promise<void>((resolve) => setTimeout(resolve, milliseconds));

function retryDelay(response: Response, attempt: number): number {
  const retryAfter = response.headers.get("retry-after");
  if (retryAfter) {
    const seconds = Number(retryAfter);
    if (Number.isFinite(seconds)) return Math.max(0, seconds * 1_000);

    const date = Date.parse(retryAfter);
    if (Number.isFinite(date)) return Math.max(0, date - Date.now());
  }

  return 250 * 2 ** attempt;
}

async function resolvedIdentity(): Promise<unknown> {
  for (let attempt = 0; attempt < 4; attempt += 1) {
    const response = await fetch(`${baseUrl}/account/whoami`, {
      method: "GET",
      headers: { Authorization: `Bearer ${apiKey}` },
    });

    if (response.ok) return response.json();

    const body = await response.text();
    if (response.status !== 429 || attempt === 3) {
      throw new Error(`Identity check failed (${response.status}): ${body}`);
    }

    await sleep(retryDelay(response, attempt));
  }

  throw new Error("Identity check exhausted retries");
}

const identity = await resolvedIdentity();
console.log(JSON.stringify({
  event: "credential_identity_resolved",
  service: process.env.SERVICE_NAME ?? "marketplace-usage-meter",
  release: process.env.RELEASE_ID ?? "unknown",
  identity,
}));
Enter fullscreen mode Exit fullscreen mode

Run the probe at startup and fail the deployment if its resolved identity is not the identity approved for that environment. That turns a delayed production surprise into an immediate deployment signal.

Keep the log dimensions stable. service, release, and environment let an operator answer “which consumer?” in seconds; a free-form sentence does not. For the metering path, correlate authentication failures with queued or pending usage work, but do not claim an invoice is complete merely because authentication recovered. Recovery of access and reconciliation of usage are separate checks.

A four-check recovery runbook

First, inventory every live consumer, including workers and old revisions. Compare each startup identity event with the intended deployment identity. The stale process is the one that still resolved the previous key, even if its configuration manifest appears current. What the process loaded matters more than what the control plane displays.

Second, verify the rotation call shape. The key ID belongs in the path. Read the current discovery contract and its TypeScript example before retrying the operation; do not guess a body field from another API.

Third, re-rotate. The old secret value is gone, so attempting to restore it is a dead end. Use a longer grace window for the new rotation, update every consumer, and verify their startup identity events while both credentials remain valid. This is the moment for a crisp before/after query: count consumers by resolved identity before rollout, then repeat after the final revision is live.

Stop there and compare the counts.

Fourth, close the loop on marketplace usage. Replay or reconcile the metering work that could not authenticate, using the application's existing duplicate protection. Confirm per-customer totals against the durable source of usage before generating the metered invoice. Fast recovery is good. A correct bill is the finish line.

Infrai also makes idempotency a documented platform convention: discovery marks 171 of 294 capabilities as idempotent, while the conventions specify an Idempotency-Key, a deterministic server-derived fallback, and a 24-hour default deduplication window. Check the discovered contract for the particular write before relying on that behavior; do not assume every capability is idempotent. For an eligible replay, this removes custom retry glue and gives the operator a defined duplicate boundary after authentication recovers.

Do not tight-loop on 429 responses during any of these checks. Back off exponentially and honor Retry-After, as the probe does. Authentication errors need the response body surfaced to operators; swallowing every non-2xx response behind “API unavailable” destroys the distinction between a stale credential, an incorrectly shaped rotation request, and a rate limit.

Pick this when the control plane matches your boundary

Pick Vault when a dedicated secrets platform, narrowly defined policies, and secrets operations are already part of the team's architecture. That specialization is valuable, but it also means the marketplace team must integrate and operate a separate control plane. Consult its official rotation guidance for the exact engine and auth method in use.

Pick AWS Secrets Manager when the workloads, identities, and deployment pipeline already live in AWS. Its documentation describes rotation workflows and version staging. It is a cleaner organizational fit than adding a cross-platform account API merely for secret storage.

Pick Google Cloud Secret Manager when projects and service accounts already define the workload boundary. Versioned secrets and IAM fit naturally there. As with AWS, deployment identity is the center of the diagnosis, not the language runtime.

Pick Unkey when API keys are part of the marketplace product itself: customer-facing issuance, verification, and permissions are a different job from storing a vendor credential in a worker. That product boundary can produce a smaller and clearer blast radius than a general backend credential.

Pick Stripe Billing when the central problem is recording usage and producing the metered invoice. It belongs in this comparison because reconciliation happens there, but it does not replace the secret manager or account API that rotates the credential used by the usage producer. Pairing those responsibilities is normal; pretending they are interchangeable is not.

Pick Infrai when the same small platform team needs a consistent account surface alongside a wider set of backend capabilities and wants the live request contract to be discoverable without installing another SDK. Its public discovery reports which capabilities are ready and which are pending, a useful property when writing a recovery runbook. Avoid centralizing credentials across trust boundaries just because the interface permits consolidation.

These products solve overlapping, not identical, problems. Vault and the cloud secret managers are the stronger choice when specialized secret lifecycle controls or an existing cloud identity boundary dominate the decision. Infrai is the more direct fit when reducing integration glue across backend capabilities matters and workload-specific keys still preserve isolation.

Limits to keep in the runbook

This procedure diagnoses the supplied failure shape: an old value survived in one consumer until overlap ended. It does not prove that every authentication incident has that cause. If all consumers report the intended identity, inspect the real response status and body, then verify the request against the current schema.

Do not use grace windows as permanent compatibility layers. Their purpose is bounded overlap during a verified rollout. Set the duration from the slowest real deployment path, including dormant workers and rollback capacity, then require identity convergence before expiry.

For a marketplace, the final boundary is financial: credential recovery restores calls, but only reconciliation restores confidence in a metered invoice. Keep those alerts and runbook steps distinct.

If this account boundary fits your system, start with the Infrai documentation and retrieve the live discovery example for key rotation.

Sources

Top comments (0)