From one switch to a control panel: meet `dataCollection`
This post and its code examples focus on the JavaScript SDKs. If you’re on another platform, it’s still worth reading to understand why we made the change and what’s coming your way.
We’re replacing the boolean sendDefaultPii with a new option called dataCollection. The old switch was all or nothing: turn it on and you got everything, leave it off and you got only a fraction. If you’ve ever wanted the request headers without the cookies, or your GenAI inputs without also shipping user emails, you know where that falls short. dataCollection turns that one switch into something closer to a control panel, where each category of data is a dial you can turn up, turn down, or filter.
What’s changing, and when
dataCollection is coming to every Sentry SDK, and you may have already spotted the option in the JavaScript SDKs as it’s been available since 10.57.0. The version 11 release is where dataCollection becomes the new default option, removing sendDefaultPii for good. The concept will be the same across platforms, but the exact defaults and migration steps may differ, and each SDK will cover its own specifics in its release notes.
For our v11 JavaScript SDKs this is a behavior change, not a rename. The new defaults collect more than the old ones did. sendDefaultPii is already deprecated and will be removed in v11, and the other Sentry SDKs will retire it on their own timelines, so dataCollection is where all of this is headed.
PII vs. sensitive data
The SDK treats two kinds of data differently. PII (or Personally Identifiable Information) is anything tied to a person: a user ID, email, username, name. Sensitive data is credentials and secrets, things like passwords, tokens, and API keys.
PII is collected by default with dataCollection. User identity is often what turns a confusing error into an obvious one, and when you’d rather not have a given category, you opt out with a single line like userInfo: false.
dataCollection only controls what the SDK collects automatically. Anything you attach manually is still sent. If you call Sentry.setUser(...) and also set dataCollection: { userInfo: false }, that user data still gets sent, because you set it explicitly.
Sensitive data is never collected automatically, and that hasn’t changed. Take HTTP headers, which the SDK collects by default. The header names all come through, but any value whose key matches the built-in denylist (auth, token, password, secret, and similar) is replaced with [Filtered] before the event leaves your app. You get the header names without the credential values.
What changed in the defaults (JavaScript SDK v11)
The v11 defaults are more permissive than the v10 ones, and we’d rather you read that here than find it in production. Where an unset sendDefaultPii used to give you the restrictive baseline, an unset dataCollection now collects several categories by default, since those are the ones that make your issues useful with no manual setup.
| Category | v10 default (sendDefaultPii off) | v11 default |
|---|---|---|
userInfo | false | true |
cookies | not collected | true |
httpHeaders | request + response, PII scrubbed | request + response |
httpBodies | not collected (size only) | all request/response (truncated) |
urlQueryParams | true | true |
genAI | inputs + outputs not collected | inputs + outputs |
databaseQueryData | false | true |
stackFrameVariables | true | true |
frameContextLines | 7 | 5 (same default as other SDKs) |
If you’d rather not collect HTTP request data, database queries, or GenAI inputs and outputs, read this table closely before you upgrade. Look hardest at request and response bodies, since that’s the most likely place for sensitive values to show up.
Setting up dataCollection, two ways
Most people upgrading to v11 land in one of two camps. Find your migration path below.
1. Previous sendDefaultPii: true
If you were already running sendDefaultPii: true, the v11 default matches what you had, so the whole migration is deleting the option.
// v10
Sentry.init({ sendDefaultPii: true });
// v11, same behavior, now the default
Sentry.init({});2. Previous sendDefaultPii: false (or unset)
The “zero-config” approach in v10 behaved like sendDefaultPii: false. In v11 it collects more.
If you want to keep the restrictive v10 behavior, this is the case that needs work. Leaving dataCollection unset opts you into the broader collection, so set the options explicitly to match the old sendDefaultPii: false behavior:
// v11, preserves the v10 default
Sentry.init({
dataCollection: {
userInfo: false,
cookies: false,
httpHeaders: {
request: { deny: ['forwarded', '-ip', 'remote-', 'via', '-user'] },
response: { deny: ['forwarded', '-ip', 'remote-', 'via', '-user'] },
},
httpBodies: [],
urlQueryParams: { deny: ['forwarded', '-ip', 'remote-', 'via', '-user'] },
genAI: { inputs: false, outputs: false },
databaseQueryData: false,
graphQL: { document: false, variables: false },
},
});Granularity for what you really need
While the default configuration of dataCollection is convenient, the granularity allows you to tailor it to your needs. The key-value fields for cookies, urlQueryParams, and both httpHeaders.request and httpHeaders.response accept more than a plain on or off. You can pass true, false, an allow list, or a deny list.
Keep the headers you actually debug with and deny the ones that carry values you’d rather not store. Allow a specific set of query params and drop the rest. Collect what’s useful, leave out what’s risky, and draw the line wherever your app needs it.
Filtering the data that dataCollection doesn’t cover
dataCollection handles the categories the SDK gathers automatically (manually attached data is always sent, see above in “PII vs. sensitive data”). When you need to redact or drop something specific that falls outside those categories, the event and span hooks are still there.
For error events, beforeSend runs before anything is sent, so it’s still where you strip PII by hand or drop an event entirely by returning null. Nothing about that changes in v11.
Version 11 also turns on span streaming mode by default. Instead of bundling spans into a single transaction at the end, the SDK sends them in batches as they finish. To modify or redact span data, use beforeSendSpan.
Sentry.init({
dsn: 'example.com',
// In v10 you may have wrapped this in withStreamedSpan(). In v11 you can remove that wrapper
beforeSendSpan: (span) => {
// In stream mode the span is a StreamedSpanJSON, so 'op' lives on attributes
if (span.attributes?.['sentry.op'] === 'db.query') {
// and 'description' is now 'name'
span.name = '[filtered]';
}
return span;
},
});beforeSendSpan can only modify spans, it can’t drop them. To drop spans in v11’s stream mode, use ignoreSpans rather than the old beforeSendTransaction or ignoreTransactions, neither of which is available once you’re streaming.
Sentry.init({
dsn: 'example.com',
ignoreSpans: [
'healthcheck',
{ name: /^GET \//, attributes: { 'http.route': '/api/status' } },
],
});Between dataCollection for the broad categories and these hooks for the specifics, you can get the data exactly how you want it before any of it leaves your app.
Before you upgrade
Read the defaults table and decide whether the new baseline suits you or whether you want to dial anything back. Take a look at your data-scrubbing config, with request and response bodies at the top of the list. Stream mode is on by default in v11, so check your span filters too. If you drop spans with beforeSendTransaction, move them to ignoreSpans. If a Sentry.withStreamedSpan() wrapper is left over from a v10 setup, unwrap it. Everything else you can tune later, one dial at a time.
If you’re not using the JavaScript SDKs, keep an eye on your own SDK’s release notes, because dataCollection is on its way to you too, with a migration guide written for your platform. The full JavaScript SDK option list lives in the dataCollection docs, and the reasoning behind it is written up in the SDK data-collection spec. We think the control panel will feel a lot more comfortable than the switch ever did.