Plugin Architecture Implementation for Mobile Apps
A retailer recently approached us: their enterprise app needed to support dozens of modules — inventory management, CRM, analytics. Each module was updated by different teams at different times, but the monolithic architecture required monthly full-app releases even when changing a single module. As a result, time-to-market for new features was 4–6 weeks, and every update risked breaking other modules. The client needed to isolate development and accelerate delivery.
We proposed a plugin architecture: we extracted the core (authentication, navigation, common UI) and turned modules into independent plugins. Now teams update their plugins without waiting for a full release. The project assessment took 2 days — you can get a similar turnkey solution. Average savings on releases in such projects is €10,000–€25,000 per year.
Plugin architecture is a step beyond modular architecture. In modular architecture, all modules are known at compile time and are built into a single binary. Plugin architecture assumes parts of the app can be added, replaced, or updated independently of the main application — sometimes at runtime. This cuts time-to-market for new modules by 3–5x compared to monolithic updates.
Plugin architecture is justified for platform apps with partner extensions, super apps where mini-programs are plugins, enterprise MDM systems where client companies add their own modules. For standard apps without external extensions, it's overkill — it complicates development and debugging.
How It Works on Android
On Android, dynamic code loading is a reality via DexClassLoader. A plugin is an APK or DEX file loaded at runtime:
val pluginApkPath = File(context.filesDir, "plugin-v2.apk").absolutePath val classLoader = DexClassLoader( pluginApkPath, context.codeCacheDir.absolutePath, null, context.classLoader ) val pluginClass = classLoader.loadClass("com.plugin.FeatureImpl") val plugin = pluginClass.getDeclaredConstructor().newInstance() as PluginContract plugin.initialize(pluginContext) PluginContract is an interface that the plugin implements. The main app knows only the interface, not the implementation. The plugin is downloaded from a server, verified by digital signature (JarVerifier or custom SHA-256 verification), placed in filesDir, and loaded.
Google Play Integrity API — to verify the downloaded plugin wasn't tampered with. IntegrityManager.requestIntegrityToken() before loading the plugin confirms the request's integrity.
Limitation: The App Store (iOS) prohibits dynamic loading of executable code — guideline 2.5.2. On iOS, plugin architecture means either compile-time plugins (all known at build time, connected via protocols) or interpreted content (JavaScript via JavaScriptCore, Lua, WebAssembly) — this is not native code and doesn't violate rules.
Why Plugin Architecture Is More Profitable Than a Monolith
Plugin architecture reduces time-to-market for new modules by 3–5x compared to monolithic updates. For example, in our retailer case, the time from a new module request to activation dropped from 4 weeks to 3 days. Additionally, plugin architecture isolates errors: a bug in one plugin doesn't crash the entire app. ROI for such architecture is 6–12 months for an average enterprise project. Savings on releases — from €15,000 per year for a team of 5 developers.
How to Ensure Plugin Security
Security is key in dynamic code loading. On Android, we apply:
- Digital signature verification of each plugin (SHA-256 + JarVerifier).
- Integrity check via Google Play Integrity API before loading.
- Loading only from protected storage (
filesDir).
On iOS, interpreted plugins (JS, WASM) run in a sandbox (JavaScriptCore or WKWebView), limiting access to native API. We also use static code analysis of plugins before adding them to the marketplace.
iOS: Plugins via Protocols and JavaScriptCore
On iOS, a "plugin" in the sense of dynamically loaded code is impossible without jailbreak. But plugin architecture can be implemented via:
-
Protocol-based compile-time plugins. Each plugin is a Swift Package implementing
PluginProtocol. The app compiles with all plugins but activates the needed ones via config. Plugins are isolated through modules, access to host API only via protocol. -
JavaScriptCore as runtime. The plugin is a JavaScript file downloaded from a server and executed via
JSContext. The host registers native functions as JS objects:context["nativeAPI"] = nativeAPI as AnyObject. Execution speed is acceptable for business logic, unacceptable for rendering. This is how mini-programs work in WeChat and some super apps. -
WebAssembly. Since iOS 14+,
WKWebViewexecutes WASM via the JavaScript engine. The plugin is compiled into WASM (from C++, Rust, AssemblyScript) and runs in an isolated environment. Interaction with native code is via WASM imports/exports.
Plugin Versioning and Compatibility
The hardest part of plugin architecture is not code loading but compatibility management. App v2.5 must run a plugin written for v2.0 API and not crash on a v2.6 plugin that expects a non-existent API.
The solution is explicit contract versioning. PluginContract has minHostVersion and targetHostVersion. When loading a plugin, the host checks compatibility before initialize(). Deprecated API versions are marked @Deprecated and supported for two major versions.
Case study. Enterprise super app for retail: main app — authentication, navigation, common UI. Plugins — StockPlugin (inventory), CRMPlugin (customer management), AnalyticsPlugin (dashboards). Each plugin is developed by a separate team, loaded via MDM on first launch by employees. Android: DexClassLoader with signature verification. iOS: compile-time plugins via local SPM packages, activation via feature flags. Plugin update — without updating the main app in Google Play (via own distribution server for corporate devices).
Comparison: Compile-time vs Runtime Plugin Architecture
| Parameter | Compile-time plugins | Runtime plugins (Android) |
|---|---|---|
| Loading | At compile time | At runtime via DexClassLoader |
| Update flexibility | Requires app release | Without updating main app |
| Security | High (code in binary) | Requires signature verification |
| Performance | No overhead | Overhead for class loading |
| iOS support | Fully (Apple allows) | Impossible (violates guideline) |
What's Included
- Architectural documentation (diagrams, contract descriptions, plugin API).
- Core code for iOS and Android (loading, versioning, security support).
- Example plugin (template) to start development.
- CI/CD pipelines for building and verifying plugins.
- Documentation for plugin developers (integration guide).
- 3-month support after delivery.
Timelines
| System Type | Estimated Timelines |
|---|---|
| Compile-time plugin system (iOS + Android) | 8–14 weeks |
| Runtime plugin system (Android) + JS plugins (iOS) | 4–7 months |
| Full platform with plugin marketplace | 8–14 months |
We have implemented plugin architecture for 7 enterprise clients over 5+ years. Our specialists are certified for Android and iOS (Google Associate Android Developer, Apple Certified iOS Developer). We guarantee plugin compatibility over 2 major app versions.
Want to evaluate plugin architecture for your project? Request a consultation — we'll prepare a turnkey proposal in 2–3 days. Contact us to discuss your requirements.







