
Running user code in Firecracker microVMs and parsing documents in a separate service
Each run of user-written Python gets its own Firecracker microVM on Azure, with fixed memory, no network by default and no platform secrets, and documents are parsed in a service of their own.
- Partner
- A multinational advisory firm
- Period
- October 2024 to January 2026
- MicroVM per run
- 1
- Created for the run and discarded after it
- Memory per run
- 1 GB
- Fixed by the microVM, so code cannot exceed it
- Network by default
- None
- An allowlist where a step needs one
The challenge
Users needed to write custom Python transformations and bring PDFs and office documents into pipelines and knowledge bases. User code cannot be trusted with the platform's secrets or network, and running it or heavy parsing inside the main backend would let one job slow or stop the platform for everyone.
What we built
A code execution service that runs each job in its own Firecracker microVM on an Azure Virtual Machine Scale Set, restored from a snapshot with 1 vCPU and 1 GB of memory, no network by default and no platform secrets, and a Docling-based parsing service that accepts files or URLs and returns structured text.
What was delivered
- Every run isolated in its own microVM, discarded when the run ends
- Memory, network and time limits enforced from outside the user's code
- Document parsing for pipelines and knowledge sources
Partner background
Our partner is a multinational advisory firm whose teams work with large volumes of documents, spreadsheets, databases and email. It wanted one internal platform where those teams could build data pipelines and AI agents themselves, instead of commissioning a new application for each need. The platform had to run inside the partner's Microsoft 365 and Azure environment, keep each team's work separate, and move work from experiment to production through controlled environments. This case study covers one part of that platform; nine case studies describe the whole.
The challenge
Custom logic is unavoidable
No library of predefined steps covers every transformation. Users need to write code, and that code can be slow or memory-hungry.
User code is untrusted
Code written by any user can try to read files, environment variables or the network. A separate process inside the same container does not stop it.
Shared resources
A runaway job inside the main backend would affect every user of the platform.
Documents are not data
PDFs and office files must be converted to structured text before a pipeline or knowledge base can use them.
Objectives
- Run each piece of user code in its own virtual machine
- Give user code no network and no access to platform secrets
- Enforce memory and time limits that code cannot exceed
- Admit only as many runs as the hosts can hold
- Convert documents to structured text for pipelines and agents
Our role
CharCentric provided technical leadership and architecture within a multidisciplinary engineering team, and contributed directly to implementation. The platform was built over 16 months, from October 2024 to January 2026, as a Python and FastAPI backend on Azure.
Scope and timeline
The code execution service was built between March and July 2025, and the document parsing service between April and October 2025.

Approach
A microVM per run
Each run starts in a fresh Firecracker microVM, restored from a snapshot so it starts quickly, and the microVM is discarded when the run ends. The virtual machine boundary, not a process inside a shared container, separates user code from the platform and from other runs.
Limits the code cannot exceed
Each microVM has 1 vCPU and 1 GB of memory, so a run cannot use more than its share. The root file system is read-only, code runs as a non-root user, the network is off unless a step allows specific hosts, and every run has a time limit.
Admission by capacity
The service knows how many microVMs each host can hold. Further requests wait for a free slot, and the scale set adds hosts when the queue grows.
Implementation

Hosts
Firecracker needs hardware virtualization, so the hosts are an Azure Virtual Machine Scale Set of Dsv5 series VMs, which support nested virtualization. Each microVM is started through the Firecracker jailer.
Code execution
Code and input arrive in batches over WebSockets and are passed into the microVM over vsock. Nothing from the platform's environment is passed in. Results stream back to the pipeline in batches and are read with a streaming JSON parser, so large datasets do not have to fit in memory at once.
Document parsing
The service accepts file content or a list of URLs, validates URLs and refuses private and internal addresses, keeps a cache of parsed documents keyed by content hash with a size limit and expiry, and uses Docling to produce structured text.
Platform use
The Python code transformer step uses the execution service. The document reader step and knowledge loaders use the parsing service.

Tools and technologies
| Tool | Purpose |
|---|---|
| Firecracker | A microVM for every run |
| Azure Virtual Machine Scale Sets | Hosts with nested virtualization |
| FastAPI WebSockets | Service interfaces |
| ijson | Streaming JSON parsing |
| Docling | Document parsing |
| Docker | Parsing service container |
What was delivered
- MicroVM per run
- 1
- Memory per run
- 1 GB
- Network by default
- None
- Services
- 2
- Isolated execution of user-written Python in Firecracker microVMs
- Memory, network and time limits enforced from outside the user's code
- A document parsing service for pipelines and knowledge bases
- Streaming, batched data transfer between services
Why it matters
Flexible platforms let users bring their own logic and files. Giving that work its own virtual machine, with nothing it does not need, keeps flexibility from becoming a security or reliability risk.
If your organization is planning a platform of this kind, or needs a specific part of one designed and delivered, we would be glad to discuss it.