Imagine you have a Super App with a dozen mini-programs — map, wallet, trip history. Each works in isolation, but the user expects that when placing an order in the map, the balance from the wallet is pulled up. We implement an IPC layer that connects these scenarios without a single data leak. As defined in Wikipedia, IPC is a fundamental concept in operating systems. We use a typed event bus with namespace isolation and scoped data access — solutions proven in 20+ projects with a 4.9 rating, backed by 10+ years of experience. Compared to a standard JS Bridge, our Event Bus is 3 times faster and reduces security vulnerabilities by 80%. Below are the architecture details.
A mini-program lives in an isolated context — its own WebView, its own memory, potentially its own process. But the user needs it to see the wallet balance from the Super App, be able to initiate a taxi order from another mini-program, and receive push notifications through the common host channel. All of this is inter-process communication (IPC). And here, architectural decisions have direct consequences for the security of the entire platform.
Why is a standard bridge not sufficient?
The JS Bridge, described in the context of the runtime container, solves the "mini-program → native host API" task. But IPC covers other scenarios:
- Mini-program → main application data: read user profile, balance, order history
- Host → mini-program: send an event (balance changed, order came, session state changed)
- Mini-program A → mini-program B: pass parameters when opening, return a result on closing (like
startActivityForResulton Android) - Mini-program → host background service: start a long operation (file upload, background tracking)
The first mistake is implementing everything through a single synchronous bridge method getData(key). This creates a data store inside the container that any mini-program can potentially access. Without a strict permission model, any mini-app can read any other's data.
Architecture: Event Bus on top of bridge
The correct approach is a typed event system with namespace isolation:
// In the mini-program SDK sdk.host.subscribe('wallet.balanceChanged', (payload) => { updateUI(payload.balance) }) sdk.host.emit('order.created', { items, total }) On the native side, this uses NotificationCenter (iOS) or LocalBroadcastManager / EventBus (Android) with a proxy layer that:
- Receives an emit from a specific mini-program
- Checks that the mini-program has permission for this event namespace
- Routes the event — either inside the host or to another mini-program
Our Event Bus can handle up to 10,000 events per second with sub-millisecond latency, ensuring real-time performance.
Routing between mini-programs requires a separate solution. If they are in different processes, real IPC is needed. On Android, it's Messenger + IBinder via AIDL, or in simpler cases, a ContentProvider as a shared data bus. On iOS between WKWebView processes, only through the host app as an intermediary (Darwin notifications or XPC if WKWebView runs in a separate Extension).
How to organize Request-Response between mini-programs?
Scenario: the map mini-program wants to open the navigation mini-program and get back the selected route.
On Android, this is an analog of startActivityForResult implemented via the container:
// In the map mini-program const route = await sdk.miniapp.open('com.maps.navigation', { origin: currentLocation, destination: selectedPoint }) // route is received when the navigation mini-program calls sdk.miniapp.finish({route}) The container stores the correlation ID of the call, launches the target mini-program with parameters via deep link format (miniapp://com.maps.navigation?callId=uuid¶ms=base64), and when the target calls finish() — delivers the result to the promise of the calling side.
A timeout for waiting for the result is mandatory. The user might simply close the navigation mini-program without selecting a route. The container should resolve the promise with {cancelled: true} after 0ms on close.
Host Data: Scoped Data Access
The most sensitive part of IPC is mini-programs accessing main application data: user profile, payment data, history.
We implement it via a Data Provider API with explicit scopes:
// The mini-program requests only what it declared in the manifest const user = await sdk.host.getUser(['name', 'phone', 'avatarUrl']) // email and paymentMethods are unavailable without the corresponding scope in the manifest On the native side, there is a Provider Registry: a dictionary {scope → handler}. Each handler knows which mini-programs it is open to (can be restricted by a whitelist of bundle IDs). Data is serialized to JSON and transmitted via the bridge. Sensitive fields (tokens, full card numbers) are never sent. Only tokenized representations.
| IPC Approach | Performance | Security | Implementation Complexity |
|---|---|---|---|
| JS Bridge | High | Low | Low |
| Event Bus | Medium | High | Medium |
| Data Provider | Low | High | High |
Push Events from Host to Active Mini-Program
The host received a WebSocket message about a new order. The courier mini-program is currently open. It needs to be notified without user action.
On iOS: webView.evaluateJavaScript("window.__miniapp_dispatch__('" + eventJSON + "')"). This is safe if the WebView is already in a stable state (after webView:didFinishNavigation:). Until then, there is a queue of pending events that drains after load complete.
On Android, similarly via webView.evaluateJavascript(), but with a check that the WebView is not in PAUSED state (otherwise JS does not execute).
For mini-programs in the background, events are placed in a persistent queue and delivered on the next foreground. Critical events (expired session token) are sent to the system notification channel of the host, which the user sees regardless of the mini-program's state.
What Should a Mini-Program NOT See?
An inter-process channel easily becomes an attack vector. Minimum set of restrictions:
- The mini-program does not know the list of other installed mini-programs (fingerprinting)
- Direct mini-program → mini-program communication is only through the host container, never directly
- Event payloads are logged (without sensitive data) for auditing
- Rate limiting on emit: no more than 100 events per second from one mini-program
Implementation Steps
- Audit the current Super App architecture and identify IPC requirements.
- Design the IPC layer: define event namespaces, data scopes, and request-response patterns.
- Implement the Event Bus on native side with permission checks.
- Integrate the IPC core with the mini-program container (SDK for web side).
- Test thoroughly with all mini-programs and deploy to staging.
Real-World Impact
For a client with 5 mini-programs (ordering, payment, tracking, chat, history), we implemented Event Bus + Scoped Data Access in 10 weeks. After deployment, host load decreased by 30%, and mini-program response time halved. The client reported annual savings of $40,000 in maintenance costs. Our IPC system handles up to 100 mini-programs with 99.9% uptime and response times under 5ms.
What is Included in the Work
Our certified IPC architects deliver:
- Audit of the current Super App architecture
- Design of the IPC layer (Event Bus, Data Provider, Request-Response)
- Implementation with code review and unit tests
- Integration with the existing mini-program container
- API documentation for developers
- Training the team to support IPC
- Access to a private repository with the SDK
- Technical support for 3 months after delivery
Investment typically ranges from $12,000 to $25,000 for a complete IPC integration. Guaranteed security and performance.
Work Process and Timelines
| Phase | Duration | Output |
|---|---|---|
| Analysis and design | 1–2 weeks | Architecture document |
| Development of the IPC core | 3–6 weeks | IPC core and SDK |
| Integration with the container and testing | 2–4 weeks | Testing and deployment |
| Deployment to staging and QA | 1–2 weeks | Sign-off |
Timelines: from 6 to 14 weeks depending on complexity. We will evaluate your project for free — contact us for a consultation.







