Run Multiple Apps on One PushFlo Account with Projects
A step-by-step guide to splitting two apps into isolated PushFlo projects: scoped API keys, identical code, clean channel names, and per-app monitoring.
Last week we shipped Projects — isolated namespaces for channels and API keys. This post is the practical version: taking one PushFlo account that serves two apps and untangling it, step by step, without touching application code.
The starting point (maybe this looks familiar)
You have a storefront and an internal admin tool. Both use PushFlo from the same account, so your channels look like this:
store-orders
store-notifications
admin-orders ← different app, same concept
admin-alerts
orders ← ...which app owns this one? nobody remembers
Prefixing channel names by hand works, sort of. But every developer has to remember the convention, the live console shows both apps interleaved, and one paste-the-wrong-key mistake sends admin alerts to your storefront.
Projects make the platform do this bookkeeping instead.
Step 1: Create a project
In the console, open Projects in the sidebar and click Create Project. Give it a name and a slug:
- Name: Storefront (rename anytime)
- Slug:
storefront(permanent — it's the namespace identifier)
Slugs follow the same rules as channel names: lowercase letters, numbers, and hyphens.
Prefer code? SDK v1.1.0 does it with a management key:
import { PushFloServer } from '@pushflodev/sdk/server';
const pushflo = new PushFloServer({ secretKey: 'mgmt_xxxxxxxxxxxxx' });
await pushflo.createProject({ name: 'Storefront', slug: 'storefront' });
await pushflo.createProject({ name: 'Admin Tool', slug: 'admin-tool' });
The Free plan includes 1 project, Starter 3, Pro 10, and Business unlimited — so a two-app split fits on Starter with room to spare.
Step 2: Create project-scoped API keys
Go to API Credentials, select the Storefront project in the sidebar switcher, and create a credential. That's it — because a project was selected, the key pair (pub_... and sec_...) is scoped to Storefront. Repeat for Admin Tool.
This is the entire trick. The project lives in the key.
Step 3: Change... nothing
Here's the storefront's real-time code before projects:
const client = new PushFloClient({
publishKey: process.env.NEXT_PUBLIC_PUSHFLO_KEY,
});
client.subscribe('orders', {
onMessage: (message) => updateOrderList(message.content),
});
And here it is after migrating to a project:
const client = new PushFloClient({
publishKey: process.env.NEXT_PUBLIC_PUSHFLO_KEY, // ← new scoped key in the env var
});
client.subscribe('orders', {
onMessage: (message) => updateOrderList(message.content),
});
Identical. You swap the environment variable, redeploy, and the app now lives in its namespace. The server side is the same story:
const pushflo = new PushFloServer({
secretKey: process.env.PUSHFLO_SECRET_KEY, // storefront's scoped secret
});
// Publishes to "orders" — the storefront's "orders", automatically
await pushflo.publish('orders', { orderId, status: 'shipped' });
Both apps can now call their channel orders. No prefixes, no conventions to document, no collisions. The namespacing happens on PushFlo's side, keyed off the credential — your code and your channel names stay clean.
If you're building something like live notifications, this also means your notification channels don't need app prefixes anymore either.
Step 4: Monitor each app separately
The console sidebar now has a project switcher. Pick Storefront and everything scopes to it: the dashboard shows that project's message volume and live connections, the channel list shows only its channels, and the real-time console streams only its traffic.
Each project also gets an overview page with the thing we wanted most ourselves: an at-a-glance activity badge — Active now when connections are live, or Last active 3h ago when things are quiet. With several apps on one account, you finally know which ones are actually doing something.
Switch back to "All Projects" and you get the old org-wide view — project channels show up with their namespace visible (storefront__orders), so nothing is hidden from you.
Step 5 (optional): Script your setup
Everything the console does, the management API does too. One pattern we like — provisioning a namespace per environment in CI:
const { projects } = await pushflo.listProjects();
if (!projects.some((p) => p.slug === 'storefront-staging')) {
await pushflo.createProject({
name: 'Storefront (staging)',
slug: 'storefront-staging',
});
}
The two sharp edges
Being upfront about the gotchas:
- Slugs are forever. You can rename a project's display name, never its slug. Choose boring, stable slugs.
- Deleting a project deletes its channels and their history. The keys survive and become organization-wide again. The console requires typing the slug to confirm — take the hint and double-check.
Wrapping up
Ten minutes of console clicking, one environment variable per app, zero code changes. That's the whole migration. Your channel names get simpler, your monitoring gets per-app, and the next prototype you spin up gets its own sandbox instead of polluting production's channel list.
The full API details are in the docs, and if you're weighing PushFlo against alternatives, the Pusher comparison covers how our approach differs.
Untangle your apps in ten minutes
Create a project, scope a key, swap an env var. Same code, isolated apps — free tier included.
Written by Marek
Indie developer building PushFlo — real-time messaging for serverless apps. Every post comes from running the thing in production. More about PushFlo →
Related Articles
Introducing Projects: Organize Your Real-time Apps Without Changing a Line of Code
PushFlo now has projects — isolated namespaces for channels and API keys. Group apps and environments, monitor them separately, and switch by swapping one API key.
Do You Really Need Millions of Messages? The Real-time Pricing Trap
Why most real-time services sell you quotas you'll never use. A honest look at what indie developers actually need from WebSocket infrastructure.
How to Add Real-time Features to Next.js Without Managing Servers
Learn how to add WebSocket-powered real-time features like live notifications, chat, and dashboards to your Next.js app deployed on Vercel — without running your own WebSocket server.
