Blog Post

Apps on Azure Blog
5 MIN READ

Scaling Azure Functions Python with orjson

eroman's avatar
eroman
Icon for Microsoft rankMicrosoft
Oct 24, 2025

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)
 jsonorjson
Total Time Taken10:01 min6:01 min
Average HTTP Request Time3.08 s1.8 s
Median HTTP Request Time2.16 s1.51 s
95th Percentile Request Time4.66 s3.52 s
Dropped Requests2890
Failed Requests (non-200 responses)1.02%0%
Table 2: Event Hub throughput - 1,000 messages (20 KB payload)
 jsonorjson
Total Time Taken4:11 min2:50 min
Messages per second3.985.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,000json

6.41

156 -
 orjson

4.36

229 +38.07%
10,000json

85.40

117 -
 orjson

72.80

137 +15.92%
100,000json

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.

Further Reading

Updated Oct 24, 2025
Version 1.0
No CommentsBe the first to comment