Going to production

Everything below has caused a real incident for someone. Half an hour with this list is cheaper than finding out from your users.

Keys and secrets#

  • The API secret exists only in your server environment. Search your client bundles for as_ to be sure.
  • Separate projects for development and production, so a test never spends production minutes or joins a real channel.
  • Know how to rotate: create a new key pair, deploy it, then disable the old one. Rotation is not an emergency if you have done it once.

If a secret ever reaches a client build

Treat it as public from that moment. Rotate immediately in the console and disable the old pair — a shipped binary cannot be recalled.

Token endpoint#

  • It authenticates your user first. An open token endpoint is an open door to your quota.
  • Your server chooses the identity. Never accept one from the client, or anyone can impersonate anyone.
  • Your server chooses the role. A client that asks for host and gets it can take over a stream.
  • Tokens last six hours. Issue one per session rather than one per screen.
The shape that keeps you safe
app.post('/api/rtc-token', async (req, res) => {
const user = await authenticate(req); // 1. your auth
if (!user) return res.status(401).json({ error: 'Sign in first' });
const channel = req.body.channel;
if (!(await userMayJoin(user, channel))) { // 2. your rules
return res.status(403).json({ error: 'Not allowed in this channel' });
}
const { token, wsUrl } = await applooma.createToken({
roomName: channel,
identity: user.id, // 3. YOUR id, not theirs
role: await roleFor(user, channel), // 4. YOUR decision
});
res.json({ token, wsUrl });
});

Permissions and devices#

  • Ask for camera and microphone at a moment the user understands, not on app start.
  • Handle refusal: let them join muted rather than showing a dead screen.
  • iOS needs NSCameraUsageDescription and NSMicrophoneUsageDescription, or the app terminates on first use.
  • Android needs runtime permission requests; declaring them in the manifest is not enough.
  • Browsers block autoplay with sound until the user interacts. Attach media in a click handler or offer an unmute control.

User interface#

CaseWhat users should see
JoiningA connecting state, not a frozen button.
ReconnectingA visible banner. Connections drop on mobile networks; silence looks like a crash.
Someone joins without videoTheir name or avatar, not a black rectangle.
Quota exceeded (429) or plan inactive (402)A clear message. This is a billing problem, not a network problem.
Token expiredFetch a new token and rejoin, without making them restart the app.

Before a large event#

  • Use the audience role for viewers. An audience token cannot publish, which is what keeps a large stream cheap and stable.
  • A channel holds up to 500 participants, but the practical limit depends on how many publish video. For big audiences, few publishers and many subscribers.
  • Rehearse at roughly the size you expect. Streams fail at scale in ways they never do with four people.
  • Tell us in advance if you expect an unusual peak, so we can raise limits and watch capacity: support@applooma.dev.

Usage and billing#

  • Know your plan's minutes per period and watch usage in the console. Sandbox minutes are a one-time grant that lapses after 30 days.
  • At 80% we email the account owner once. Make sure that address is one somebody reads.
  • At 100% new tokens are refused with QUOTA_EXCEEDED; outside an active period with SUBSCRIPTION_INACTIVE. Calls in progress continue.
  • Decide in advance what your app does when that happens — a queue, a waiting message, or an upgrade prompt.

Moving an existing app over#

  • Put every real-time call behind one class of your own first. The move is then hundreds of lines, not thousands, and you can keep two implementations side by side.
  • Choose the implementation per room, when the room is created, and store the choice on the room. A session that started one way finishes that way; only new rooms move, and rolling back is a flag, not a rebuild.
  • Move video live first — join, picture, comments, gifts — and run it for a week. Then voice rooms, then two-room battles (a second AppEngine) and private calls.
  • Wait for onJoined before sending anything, attach video views in onUserJoined, and read onStats when a call looks wrong before assuming the network.

Know when something is wrong#

  • Log the error code from every failed token request. A spike in QUOTA_EXCEEDED is a business event, not a bug.
  • Subscribe to webhooks for joins and leaves if session records matter to you.
  • Track how often clients reach the reconnecting state. A rise usually means a network or capacity problem worth reporting.

Privacy and consent#

AppLooma does not store your users' audio or video. Media is relayed, not recorded. What you are responsible for: telling participants when a session is being captured on your side, and meeting the consent rules that apply where your users are — they vary by country, and in some places every participant must agree.