I support family sharing across three of my apps. Ticking the box in App Store Connect is not enough, you also need the right client-side setup. On top of that there’s subscription group discipline. Get it right early and you save yourself a lot of complexity later.
What a subscription group is
A subscription group can hold multiple plans. Only one plan is active at any time. Users can upgrade or downgrade between plans and Apple handles proration. For example:
Group: Premium
├── Monthly Basic (9.99)
├── Monthly Pro (19.99)
├── Yearly Basic (89.99)
└── Yearly Pro (189.99)A user on Monthly Basic can upgrade to Yearly Pro. Apple deducts the remaining Monthly Basic balance from the Yearly Pro charge.
One group or many
If it makes sense for a user to hold two subscriptions at once, use two groups. Example: Cloud Storage plus Pro features. They can be independent, a user can subscribe to both.
If they’re dependent, one group. Example: Free, Basic, Pro tiers. A user should only ever hold one.
I got this wrong on my first app. I made Pro and a Premium Addon into two plans in the same group. When a Pro user wanted to move to Premium, Pro got cancelled and Premium went active, and the intersection of the two feature sets was simply lost. Fixing it meant splitting them into two separate subscription groups and migrating existing users. That took two months.
The family sharing toggle
On the product page in App Store Connect there’s a “Family Sharing” toggle. Flip it on and Apple does the heavy lifting: if the family organizer buys the subscription, every family member gets access. But you need to understand what that implies on the client.
Entitlement check: who’s the owner, who’s the member
import StoreKit
func checkEntitlement() async {
for await result in Transaction.currentEntitlements {
guard case .verified(let transaction) = result else { continue }
let isOwner = transaction.ownershipType == .purchased
let isFamilyMember = transaction.ownershipType == .familyShared
// ...
}
}When ownershipType == .familyShared, the user has access through the family. You may want to gate certain features behind owner status, for example only the organizer should be able to manage the subscription.
Analytics: family vs owner
Are you counting family members as separate users? If so, your MRR numbers break. My approach: count a family member as an active user, but attribute revenue only to the owner. On the server I keep a family_member_of field.
Family sharing is hard to test
You need to create a real Apple family account and sandbox-test. Adding a family member in sandbox is painful because of restrictions. What I did: on my own real family account, I installed the app on an iPad used only for this purpose and tested there. As close to production as you can get before TestFlight.
Refund and family: the tricky bits
If the family organizer gets a refund, access for every family member does not drop instantly. Apple sets a revocation_date on the receipt, but the change takes a few minutes to reach the client. My approach: keep the Transaction.updates listener running, and the moment revocation arrives, update local entitlement state and refresh the UI:
Task {
for await result in Transaction.updates {
guard case .verified(let tx) = result else { continue }
if tx.revocationDate != nil {
// downgrade the user
await appState.revokeEntitlement(for: tx.productID)
}
}
}Subscription status change notifications
Apple Store Server Notifications feed the backend too. I listen for events like DID_FAIL_TO_RENEW, GRACE_PERIOD_EXPIRED, and REVOKE. When the backend gets one:
- I don’t send push notifications to family members, they don’t know about the subscription state and it would feel like spam
- Only the organizer gets the notification
- Family members’ local cache updates on their next app launch
Pitfall: owner-only settings
If the “Manage Subscription” button in Settings is visible to a family member, the system modal opens but the member can’t cancel, the organizer owns the billing. It confuses users. On a family member I hide the button and show “Contact your organizer” instead.
Closing advice
Family sharing is not “tick it in App Store Connect and forget”. Test it on your own family account for at least three days. Write your entitlement code against the familyShared key-path. Handle refunds and revocation through the updates listener. Done right, family users are accounted for. Done wrong, access can linger for two or three days after a refund.