# Why revenue shows zero in RevenueCat observer mode

With StoreKit 2 in observer mode, purchases never appear unless you call recordPurchase. Notes from a bug I chased for a week thinking revenue was zero.

By: Necati Doğrul · 2026-08-20 · https://necatidogrul.dev/en/notes/revenuecat-observer-mode · ios, payments

A familiar setup: you do purchases yourself with StoreKit 2 and add RevenueCat in observer mode for analytics and webhooks only. `purchasesAreCompletedBy: .myApp` in `Purchases.configure`. The dashboard shows zero dollars for a week. Sandbox purchases work, App Store Connect has the transactions, RevenueCat has nothing.

## Cause

In observer mode RevenueCat can listen to StoreKit 1's transaction queue; with StoreKit 2 there is no queue. If you do not call `recordPurchase(_:)` when a purchase completes, the SDK never sees the transaction. It is in the docs, but the word "observer" makes you assume it observes on its own.

## Fix

When `Product.purchase()` returns a `verified` transaction, record it with RevenueCat before calling `finish()`:

```swift
let result = try await product.purchase()
if case .success(let verification) = result,
   case .verified(let transaction) = verification {
    _ = try? await Purchases.shared.recordPurchase(result)
    await transaction.finish()
}
```

During a migration build, do not let both sides finish transactions; one closes what the other has not seen yet.

## How I noticed

Not by looking at the dashboard. A Cloudflare Worker forwards RevenueCat webhooks to Telegram; after a week of silence I read the webhook, then the SDK log. The log had a "purchase completed by app, not recorded" line. Without a second source I would have taken zero revenue as real.

## Lesson

Observer mode does not mean "do nothing". The record call is yours. And when revenue reads zero, suspect the measurement before the product.

---
Necati Doğrul · https://necatidogrul.dev
