Tracking and fixing checkout performance in React Native with Sentry tracing
Instrument tracing for a React Native app with a Python backend to find slow HTTP requests in your checkout flow, fix them, and set up alerts and dashboards to stay on top of regressions.
Before you start
SDKs required
- @sentry/react-native installed in your mobile app
- sentry-sdk installed in your Python backend
Accounts & access
- Sentry account with a React Native project
- Python backend project in the same Sentry organization
- Access to deploy code to both frontend and backend
Knowledge
- Basic familiarity with React Native development and React Navigation
- Understanding of REST APIs and async data fetching
1 Enable tracing and set trace propagation targets
In your React Native app, initialize the Sentry SDK with tracesSampleRate set to a value greater than zero. Set tracePropagationTargets to include your Python backend URL so that Sentry propagates trace headers across services. This connects your frontend and backend into a single distributed trace.
import * as Sentry from "@sentry/react-native";
const navigationIntegration = Sentry.reactNavigationIntegration({
enableTimeToInitialDisplay: true,
});
Sentry.init({
dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
integrations: [navigationIntegration],
// Set to 1.0 for testing, lower in production
tracesSampleRate: 1.0,
// Include your Python backend so trace headers propagate
tracePropagationTargets: ["localhost", "https://your-api.example.com"],
});
2 Add time to full display on your checkout screen
Time to Initial Display (TTID) is tracked automatically when you enable the React Navigation integration. Time to Full Display (TTFD) requires you to tell Sentry when the screen is fully loaded. Use the Sentry.TimeToFullDisplay component and pass a boolean that flips to true once all content (like products on your checkout screen) has loaded.
import * as Sentry from "@sentry/react-native";
import { useState, useEffect } from "react";
function CheckoutScreen() {
const [products, setProducts] = useState(null);
const allLoaded = products !== null;
useEffect(() => {
fetchProducts().then(setProducts);
}, []);
return (
<View>
<Sentry.TimeToFullDisplay record={allLoaded} />
{allLoaded
? products.map((p) => <ProductItem key={p.id} product={p} />)
: <LoadingSpinner />}
</View>
);
}
3 Create custom spans for checkout operations
Use Sentry.startSpan to wrap the operations you care about — like the initial catalog load and the checkout process itself. Pass attributes that you can search and filter by later in the Trace Explorer.
async function loadCatalog() {
return Sentry.startSpan(
{
op: "checkout.catalog_load",
name: "Initial Catalog Load",
},
async () => {
const response = await fetch("https://your-api.example.com/api/v1/products");
return response.json();
}
);
}
async function processCheckout(cart) {
return Sentry.startSpan(
{
op: "checkout.process",
name: "Process Checkout",
attributes: {
"cart.item_count": cart.items.length,
"cart.total": cart.total,
},
},
async () => {
const response = await fetch("https://your-api.example.com/api/v1/checkout", {
method: "POST",
body: JSON.stringify(cart),
});
return response.json();
}
);
}
4 Review checkout performance in Mobile Insights
Open Mobile Insights in Sentry. Here you can see average time to display, cold start times, and transaction durations. Check the transaction list for your checkout screen. The Mobile Vitals screen shows TTID, TTFD, and screen loads across all your screens.
Mobile vitals
5 Drill into a slow checkout transaction
From the transaction list, filter by slowest transactions and click into one. The Transaction Summary shows a waterfall of all operations — HTTP requests, UI loads, and your custom spans. Look for the operations taking the most time. In the example scenario, a slow HTTP GET and POST to the backend were the main bottlenecks.
Insights overview
6 Explore spans in the Trace Explorer
Go to Trace Explorer and search for your navigation spans (for example, filter by span.op:navigation). Click into a specific trace to see the full waterfall, including the time spent in your backend. You can group by attributes, compare P50 and P95 durations, and identify where time is being spent.
7 Fix the slow backend endpoints and verify
Once you have identified the slow backend requests, optimize them (caching, query optimization, payload reduction — whatever applies). Redeploy and repeat the checkout flow. Go back to the Trace Explorer, search for recent checkout spans, and compare the new durations against the old ones. In the Trace Explorer, switch to the Visualize tab and chart the average span duration to see the improvement over time.
8 Create an alert for slow checkouts
From the Trace Explorer, with your checkout span filter active, click Save As and select Alert. Set a critical threshold (for example, average span duration over 1 second) and configure an action — like emailing your team or sending to Slack. Give the alert a descriptive name like "Checkout processing is slow." The alert will fire when performance degrades and resolve itself when things improve.
Set up alerts
9 Add a dashboard widget for checkout processing time
Go to Dashboards and open (or create) a performance dashboard. Click Add Widget and configure it:
- Set the dataset to Spans
- Set the Y-axis to avg(span.duration)
- Add a filter for
span.op:checkout.process - Name the widget something like "Checkout processing time" and save it
That's it.
Your checkout is instrumented.
Slow transactions will surface as performance issues in Sentry, with spans showing exactly where the delay happened.
- Instrumented tracing across React Native and Python
- Tracked time to initial display and time to full display for mobile screens
- Created custom spans for critical checkout operations
- Found slow HTTP requests using Mobile Insights and Trace Explorer
- Set up alerts and dashboard widgets for checkout performance
Pro tips
- 💡 Add meaningful attributes to your custom spans (like cart value, item count, or API version) so you can filter and group by them in the Trace Explorer.
- 💡 Use the Visualize tab in the Trace Explorer to chart span durations over time, then save those charts directly as alerts or dashboard widgets.
- 💡 Set
tracePropagationTargetscarefully — include only your own backend domains to avoid sending Sentry headers to third-party services. - 💡 Start with
tracesSampleRate: 1.0during development, then lower it in production to control costs. Consider usingtracesSamplerfor finer control.
Common pitfalls
- ⚠️ If you forget to set
tracePropagationTargetsto include your backend URL, your frontend and backend traces won't be connected. - ⚠️ TTFD won't be recorded if you never flip the
recordprop totrueonSentry.TimeToFullDisplay. Make sure your loading state resolves. - ⚠️ Custom spans created with
Sentry.startSpanneed an active parent span to attach to. If tracing isn't enabled or the sample rate is zero, spans won't be captured. - ⚠️ Don't set
tracesSampleRateto 0 thinking it disables tracing — it still enables the tracing pipeline but drops everything. Remove the option entirely to disable tracing.
Frequently asked questions
What's next?
Fix it, don't observe it.
Get started with the only application monitoring platform that empowers developers to fix application problems without compromising on velocity.