{"slug": "in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app", "title": "In-process vs out-of-process plugins: the design fork that shaped my Windows app", "summary": "A developer building Chauffeur, a local Windows tool for snapshotting and restoring desktop state, deliberately implemented two plugin models: in-process C++ shared libraries for performance and out-of-process add-ins for crash isolation. The choice between in-process and out-of-process effectively determines the language and safety trade-offs, with the REST API serving as both integration and version boundary.", "body_md": "I'm building Chauffeur, a local Windows tool that snapshots your whole working state across apps — open files, editor tabs, browser tabs, projects — and restores it on demand. \"Save game\" for your desktop. 100% local: no cloud, no account, no telemetry.\n\nBut this post isn't a pitch. It's about the one architecture decision that shaped everything: how do other apps plug into the core? I ended up running two completely different plugin models on purpose, and the reasoning is worth sharing.\n\nThe setup\n\nA small background service (C++/Qt 6) exposes a local REST API. Everything integrates through that single point. The question was never really \"what language\" — it was in-process or out-of-process. Those are the two real choices, and the language question mostly answers itself afterward.\n\nModel 1 — In-process plugins (C++ shared libs)\n\nThese are C++ shared libraries the core loads directly into its own address space, behind a plain extern \"C\" boundary:\n\n// Stable C ABI — no name mangling, no STL across the boundary\n\nextern \"C\" {\n\n__declspec(dllexport) int chauffeur_plugin_init(const ChauffeurHostApi* host);\n\n__declspec(dllexport) void chauffeur_plugin_shutdown();\n\n}\n\nPros: fast, share memory with the core, zero IPC overhead. Perfect for trusted, first-party, performance-sensitive work.\n\nCons, and they're real:\n\nModel 2 — Out-of-process add-ins (separate processes)\n\nThe Excel/Word add-ins (C# VSTO), the browser extensions (JS), the VS Code extension — none of them share memory with the core. They register over the local REST API and send a heartbeat:\n\nPOST /register { \"id\": \"excel\", \"type\": \"push\", ... }\n\nPOST /plugin/alive/excel // heartbeat\n\nIf one crashes, hangs, or gets killed, the core just sees a dead socket and moves on. The blast radius is one process.\n\nPros: crash isolation for free, no shared address space, no ABI headaches — and the language becomes irrelevant. C#, JS, Python, anything that speaks HTTP.\n\nCons: IPC latency, serialization, and you're now running N processes.\n\nThe lesson\n\nThe thing that surprised me: the in-process/out-of-process choice is the language choice in disguise.\n\nPicking per integration instead of forcing one model everywhere is the decision I'd make again without hesitation. The REST boundary doubles as the version boundary too — you negotiate a protocol version on /register instead of versioning a memory layout.\n\nOn exception safety\n\nIf you go in-process, try/catch around every interface call helps with well-behaved exceptions — but it does nothing against segfaults, stack smashes, or infinite loops. Those take the host with them. If you need real isolation, a process boundary is the only thing that actually gives it to you. Versioned interfaces (IPluginV1/IPluginV2) solve ABI compatibility, not crash safety. Don't conflate the two.", "url": "https://wpnews.pro/news/in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app", "canonical_source": "https://dev.to/dmaginas/in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app-40kh", "published_at": "2026-06-13 06:02:35+00:00", "updated_at": "2026-06-13 06:17:09.093837+00:00", "lang": "en", "topics": ["developer-tools"], "entities": ["Chauffeur", "Windows", "C++", "Qt 6", "REST API", "C#", "VSTO", "VS Code"], "alternates": {"html": "https://wpnews.pro/news/in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app", "markdown": "https://wpnews.pro/news/in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app.md", "text": "https://wpnews.pro/news/in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app.txt", "jsonld": "https://wpnews.pro/news/in-process-vs-out-of-process-plugins-the-design-fork-that-shaped-my-windows-app.jsonld"}}