# Opt-out requests processed within 15 business days

- **Pattern:** `ab-000630` (`ccpa-readiness.opt-out.opt-out-processing-time`)
- **Severity:** medium
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000630
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000630)

## Why it matters

CCPA § 1798.120(c) and § 1798.135(b) require opt-out requests to be processed within 15 business days of receipt. For real-time client-side opt-outs — a cookie is set and pixels stop firing immediately — this deadline is automatically satisfied. The gap is backend-processing opt-outs: requests that require staff to remove the consumer from a CRM, advertising platform audience, or data broker list. Without a tracking system and documented SLA, there is no way to prove compliance, and regulators treat the absence of tracking as evidence of non-compliance. An opt-out form that routes to an unmonitored inbox with no SLA is a CCPA violation waiting for an enforcement trigger.

## Severity rationale

Medium because the 15-business-day processing requirement under CCPA § 1798.120(c) is specific and auditable — a manual fulfillment queue with no SLA tracking is a documented non-compliance gap.

## Remediation

For real-time cookie-based opt-outs, document that the 15-day deadline is satisfied automatically. For any backend processing (removing from CRM lists, third-party advertising audiences), persist an opt-out record with a timestamp and send the consumer a confirmation email.

```ts
// app/api/privacy/opt-out/route.ts — log, confirm, and schedule third-party removal
export async function POST(req: Request) {
  const { email } = await req.json()

  await db.privacyPreference.upsert({
    where: { email },
    create: { email, optedOutAt: new Date(), type: 'sale_sharing' },
    update: { optedOutAt: new Date() },
  })

  await sendEmail({
    to: email,
    subject: 'Your opt-out has been processed',
    body: 'Effective immediately. Third-party advertising lists updated within 15 business days.',
  })

  await notifyThirdPartiesOfOptOut(email)
  return Response.json({ ok: true, processedAt: new Date().toISOString() })
}
```

Track third-party list removals in `PRIVACY_OPERATIONS.md` so you can demonstrate the 15-business-day SLA was met if a regulator asks.

## Detection

- **ID:** `opt-out-processing-time`
- **Severity:** `medium`
- **What to look for:** CCPA requires opt-out requests to be processed within 15 business days of receipt. Check whether opt-out requests are processed immediately (in real-time via the opt-out mechanism) or queued for later processing. If queued, check the queue mechanism and whether a 15-business-day SLA is tracked. For real-time opt-outs (user clicks a button and a cookie is set + sharing immediately stops), the 15-day requirement is automatically satisfied. For backend-processed requests (e.g., requests to remove a consumer's data from a CRM or third-party platform after a form submission), check whether there is an internal tracking system, SLA documentation, or workflow that ensures fulfillment within 15 business days. Check whether opt-out confirmation is sent to the consumer. Count all instances found and enumerate each.
- **Pass criteria:** Opt-out of sale/sharing takes effect immediately when the user interacts with the opt-out mechanism (real-time). For any opt-out actions that require backend processing (removal from third-party lists, CRM updates), a documented process ensures completion within 15 business days and the consumer receives confirmation. Threshold: no more than 15 business days.
- **Fail criteria:** Opt-out form submission has no documented processing SLA. Opt-out mechanism is "request-based" with no confirmation or tracking. Third-party data sharing is not stopped in real-time — only queued for future processing without a guaranteed timeline.
- **Skip (N/A) when:** Application does not sell or share personal information — document.
- **Detail on fail:** Example: `"Opt-out form submits a request to a manual inbox with no documented SLA. No confirmation email sent to consumer. No tracking of fulfillment timing."` or `"Opt-out cookie set client-side immediately, but Facebook Pixel firing is not gated on the cookie on first load — sharing may occur before the cookie is read."`.
- **Remediation:** For real-time client-side opt-outs, document that the 15-day requirement is satisfied automatically. For any backend processing, implement tracking:

  ```ts
  // app/api/privacy/opt-out/route.ts — log and confirm opt-out
  export async function POST(req: Request) {
    const { email } = await req.json()

    // Store opt-out preference
    await db.privacyPreference.upsert({
      where: { email },
      create: { email, optedOutAt: new Date(), type: 'sale_sharing' },
      update: { optedOutAt: new Date() },
    })

    // Send confirmation email
    await sendEmail({
      to: email,
      subject: 'Your opt-out request has been processed',
      body: [
        'Your request to opt out of the sale or sharing of your personal information',
        'has been processed and is effective immediately.',
        '',
        'If your information was previously shared with third-party advertising partners,',
        'we will notify those parties of your opt-out within 15 business days.',
      ].join('\n'),
    })

    // Schedule third-party notification if applicable
    await notifyThirdPartiesOfOptOut(email)

    return Response.json({ ok: true, processedAt: new Date().toISOString() })
  }
  ```

---

## External references

- ccpa §1798.120(c)
- ccpa §1798.135(b)
- nist PT-6

Taxons: privacy-consent, regulatory-conformance

HTML version: https://auditbuffet.com/patterns/ab-000630
