Performance at scale matters. With native orjson support, your Azure Functions Python apps can handle more requests, process data faster, and deliver smoother serverless experiences.
Introduction
Delivering high-performance serverless applications is at the heart of Azure Functions. Azure Functions serves countless customer workloads across scenarios like APIs, event processing, and automation. To ensure great performance at scale, we’re always looking for opportunities to reduce latency and increase throughput — especially for common operations like JSON serialization and deserialization.
To that end, we’ve introduced support for orjson, a fast JSON library, into the Python worker for Azure Functions. When customers add orjson to their Function App environment, the Azure Functions runtime will automatically switch to using orjson instead of the standard json module — unlocking significant performance gains without any application code changes.
Motivation: Why orjson Matters
JSON serialization is fundamental to many serverless workloads — from processing HTTP payloads to streaming events. Every Azure Function in Python that communicates via HTTP or interacts with event-based services such as Event Hubs, Service Bus, or Cosmos DB involves reading and writing JSON. JSON handling is split between the Azure Functions Python Worker and the Azure Functions Python Library. The library is responsible for serializing Python objects to JSON and deserializing JSON inputs into Python objects, while the worker simply transports the raw data to and from the function. This separation means that JSON processing is concentrated in the library, making it a key factor for function performance, as every input and output must pass through these conversions.
The standard Python json library, while reliable, isn’t optimized for high-throughput scenarios. As payload sizes grow or concurrency increases, JSON serialization can become a performance bottleneck, affecting both latency and scalability. To help improve latency and throughput, the Azure Functions Python library now uses orjson automatically if it’s listed in your requirements.txt or installed in your virtual environment. This allows you to benefit from faster JSON processing without changing your code. If orjson isn’t included, the library falls back to the standard json module. We wanted to give customers an easy way to improve performance simply by including a faster library — without requiring them to refactor their applications.
azure-functions
orjson
Why orjson Outperforms Other JSON Libraries
When it comes to JSON serialization and deserialization in Python, developers often use libraries like json (built-in), simplejson, or ujson. While these can offer moderate improvements over the standard library, orjson consistently outperforms them in both speed and memory efficiency.
- Native Rust Implementation: orjson is written in Rust, enabling highly optimized memory management and performance beyond what pure Python or C extensions typically achieve
- Faster Serialization and Deserialization: Benchmarks show orjson can be 2-4x faster than ujson and up to 10x faster than json when working with large or deeply nested payloads
- Compact Binary Output: orjson produces more compact JSON output, which can reduce payload sizes — especially impactful in high-throughput or bandwidth-sensitive scenarios
- Strict Standards Compliance: Unlike some faster JSON libraries, orjson conforms to RFC 8259 by default, avoiding silent errors in interoperability
For Azure Functions, this means customers don’t just get incremental improvements over the standard json — they get one of the fastest JSON solutions available in Python today, leading to meaningful latency and throughput gains for real-world serverless applications.
Measuring Performance Gains
We benchmarked the improvements using realistic workloads with a payload size of 20 KB, chosen to reflect common message sizes in customer scenarios. Load tests were conducted using k6 for HTTP and internal tooling for Event Hub scenarios. The benefits of orjson became even more pronounced as payload sizes increased. Results were measured by taking the median of three runs for each test case.
Testing Locally
Table 1: HTTP performance - 10,000 requests (20 KB payload)
| json | orjson | |
| Total Time Taken | 10:01 min | 6:01 min |
| Average HTTP Request Time | 3.08 s | 1.8 s |
| Median HTTP Request Time | 2.16 s | 1.51 s |
| 95th Percentile Request Time | 4.66 s | 3.52 s |
| Dropped Requests | 289 | 0 |
| Failed Requests (non-200 responses) | 1.02% | 0% |
Table 2: Event Hub throughput - 1,000 messages (20 KB payload)
| json | orjson | |
| Total Time Taken | 4:11 min | 2:50 min |
| Messages per second | 3.98 | 5.88 |
Testing in Cloud
When building high-throughput apps on Azure Functions, even small optimizations in data handling can make a measurable difference. We ran a series of benchmarks in the cloud to compare the default Python json parser with orjson to evaluate the impact on throughput and latency across different payload sizes, along with the impact of other platform pieces.
HTTP - Test Setup and Results
- Azure Functions Flex Consumption Apps configured with 100 max instances, 2 GB memory (keeping defaults)
- Using the Load Testing feature within Azure Functions, built on Azure Load Testing - 20 ALT engines, 250 VUH per instance.
- 5 minutes sustained load per test.
- Payload sizes tested: <1 KB (minimal), 5 KB (small), 35 KB (medium), 992 KB (large) (files from Azure REST API Specs)
|
JSON Size |
Parser |
Errors (%) |
Avg Response Time (ms) |
Throughput (req/s) |
% Diff vs json |
|---|---|---|---|---|---|
|
1 KB |
json |
0.00% |
780 |
10,477.78 |
– |
|
|
orjson |
0.00% |
736 |
10,632.50 | +1.48% |
|
5 KB |
json |
0.001% |
856 |
10,091.14 |
– |
|
|
orjson |
0.03% |
861 |
10,337.38 | +2.44% |
|
35 KB |
json |
0.00% |
963 |
7,305.19 |
– |
|
|
orjson |
0.00% |
933 |
7,763.25 | +6.27% |
|
992 KB |
json |
0.00% |
5,338 |
1,051.21 |
– |
|
|
orjson |
0.00% |
4,937 |
1,083.96 |
+3.12% |
Fig: Client-side metrics view from Azure Load Testing (ALT) showing the throughput and response time over the test duration. Test case: Without orjson with 35KB JSON data.
Service Bus - Test Setup and Results
- Azure Functions Flex Consumption Apps configured with 100 max instances, 2 GB memory (keeping defaults)
- Using Service Bus LoadGen with a batch size of 100, single worker
| # SB Messages | Parser | Total Time Taken (s) | Throughput (msg/s) | % Diff vs json |
| 1,000 | json |
6.41 | 156 | - |
| orjson |
4.36 | 229 | +38.07% | |
| 10,000 | json |
85.40 | 117 | - |
| orjson |
72.80 | 137 | +15.92% | |
| 100,000 | json |
959.50 | 104 | - |
| orjson |
847.20 | 118 | +12.43% |
Note: JSON operations occur in the Functions Python Library during batch processing
Challenges & Lessons Learned
Integrating a third-party library like orjson at the worker level came with several challenges:
- Compatibility: Ensuring orjson works seamlessly across supported Python versions (3.9 – 3.13) required rigorous testing to handle subtle differences in serialization behavior
- Conditional Loading: We designed the runtime to dynamically switch to orjson only when it’s available in the customer’s virtual environment — avoiding unnecessary dependencies or errors when orjson isn’t installed
- Benchmark Accuracy: Accurately measuring improvements meant accounting for cloud transience, cold starts, and varying payload patterns to produce consistent results
Success Stories
- Reduced Latency Under Load: Workloads with larger payloads showed improvements of up to 40% reduction in average request times and elimination of dropped requests
- Better Throughput for Event Processing: Event Hub scenarios achieved nearly 50% higher message processing rates, helping applications keep up with bursty or high-volume events
- Drop-in Improvement: Customers benefit instantly just by adding orjson in their requirements — no code changes needed
Future Directions
- Enhanced Developer Guidance: Documenting best practices and recommendations for customers to adopt orjson effectively and understand when it provides the most benefit
- Deeper Worker Optimizations: Exploring further opportunities to improve serialization, deserialization, and other performance-critical paths in the Python worker
Conclusion
By supporting orjson in the Python worker, we’re making it easier for developers to get significant performance gains with a simple dependency addition. These improvements help reduce latency, improve throughput, and deliver better customer experiences for Python-based Azure Functions apps. For further performance tips, check out the Azure Functions Python developer guide. We hope these insights inspire you to explore how dependency choices can drive real performance improvements in your serverless applications.