# Going Live Checklist

Before going live, check the following to launch smoothly.

## Best Practices

- Replace development tokens with server-issued, expiring user tokens.
- Never ship secrets or API keys in the client app.
- Reset offline storage before switching users to avoid data leaks.
- Profile custom components for re-render hotspots in message lists.
- Validate permissions and notifications across both platforms.

### Usage of Tokens

[Development tokens](/chat/docs/javascript/tokens_and_authentication/) are fine for local testing, but they disable auth and are not for production. Use proper auth before release. For extra security, use expiring tokens and a [token provider](/chat/docs/javascript/tokens_and_authentication/#how-to-refresh-expired-tokens/) to refresh them.

### Sensitive Data Storage

Never store secrets (like your Stream secret) on-device. A compromised device can expose them and allow destructive actions.

### Logging out

If you use offline storage, clear it on logout and wait for logout to complete before switching users. Otherwise you can corrupt state or crash.

```tsx
import { QuickSqliteClient } from "stream-chat-react-native";

const logout = async () => {
  // Reset and clear the local database if offline storage was enabled.
  QuickSqliteClient.resetDB();

  // Disconnect the connected user for the chat client.
  chatClient?.disconnectUser();

  // Set the current chat client to null.
  setChatClient(null);
};
```

### Performance for Custom components

When a context value updates, [all consumers re-render](https://reactjs.org/docs/context.html#contextprovider). Our components use memoization and custom `areEqual` checks to reduce unnecessary re-renders, especially in message lists. Apply the same pattern in custom components.

Example: a component reading `PaginatedMessageListContext` will re-render often:

```tsx
import { usePaginatedMessageListContext } from "stream-chat-react-native";
import { Text } from "react-native";

const MySenderComponent = () => {
  const { messages } = usePaginatedMessageListContext();
  const latestMessageSender = messages[messages.length - 1]?.user?.name;
  console.log("Render.");

  return <Text>{`Last Sender: ${latestMessageSender}`}</Text>;
};
```

Reduce re-renders by splitting context access from a memoized presentational component with a custom `areEqual`:

```tsx
import React from "react";
import { usePaginatedMessageListContext } from "stream-chat-react-native";
import { Text } from "react-native";

const MySenderComponentWithContext = ({ latestMessageSender }) => {
  console.log("Rendered");

  return <Text>{`Last Sender: ${latestMessageSender}`}</Text>;
};

const MemoizedMySenderComponent = React.memo(
  MySenderComponentWithContext,
  (prev, next) => prev.latestMessageSender === next.latestMessageSender,
);

const MySenderComponent = () => {
  const { messages } = usePaginatedMessageListContext();
  const latestMessageSender = messages[messages.length - 1]?.user?.name;

  return (
    <MemoizedMySenderComponent latestMessageSender={latestMessageSender} />
  );
};
```

With this pattern, the `Text` component renders on mount and only updates when `latestMessageSender` changes.


---

This page was last updated at 2026-03-06T17:06:18.413Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/react-native/guides/going-live-checklist/](https://getstream.io/chat/docs/sdk/react-native/guides/going-live-checklist/).