Blog
Major upgrades released!
Happy Halloween, everyone!
We’re thrilled to announce that we’ve completed a significant upgrade rollout. Here’s a summary of the updates and what we’ve accomplished.
Complete Overhaul of Code Architecture
Our core codebase has been completely rewritten from the ground up. We faced several key challenges during this process. Initially, our code ran in a Docker container based on the Azure Functions runtime, a remnant of our legacy days. Although we transitioned to Google Cloud Run long ago, the Azure Functions runtime posed issues for a few reasons: it was built on Debian 11, which bloated our Docker image size, and it didn’t adhere to standard .NET web API practices. Additionally, we noticed a memory leak associated with our LibreOffice endpoints.
Our rewrite completely removed the Azure Functions runtime, replacing it with a streamlined .NET 8 Web API. This change not only reduced the memory leak issues we encountered but also allowed us to align with best practices in .NET development.
Moving away from Azure Functions also enabled us to adopt a slimmer Docker container, migrating to one based on Alpine Linux.
Another challenge we faced was that our core containers—Chrome, LibreOffice, PdfSharp, and Wkhtml—were built and deployed as individual codebases. This fragmented approach complicated deployment and management. With the rewrite, we consolidated everything into a single codebase. The best part? The new consolidated Docker container, featuring all functionality on Alpine Linux, is smaller in image size than either the Chrome or LibreOffice containers individually! This simplified container will make things much easier for our Enterprise Customers who purchase our Docker container directly.
This streamlined architecture will reduce our hosting costs while simultaneously increasing reliability.
Upgraded Chrome and LibreOffice Versions
We’re now running the latest versions of Chrome and LibreOffice, along with updated libraries for all our dependencies. This means we benefit from the latest security updates and enhancements that come with these underlying engines. As of this writing, we’re deployed on Chrome 130.
Fonts and Languages
With our transition to an Alpine Linux-based Docker container, we’ve installed a wide range of fonts, including all languages supported by Noto Fonts. There should be very few languages unsupported at this time.
Additionally, we’ve included the Noto Font for emojis, a long-requested feature. Now you can print emojis in your PDFs!
Output as Binary
You can now specify a query parameter in your API requests: outputBinary=true
(default is false). This returns the processed file as binary rather than JSON with a URL to our storage bucket. In this scenario, the file never touches our storage buckets. Certain endpoints, such as /zebra
, /zip
, and GET requests for PDF generation, have outputBinary=true
by default. This is a valuable enhancement for customers who prefer not to store their files on our buckets.
Automated Swagger Spec
Our swagger documentation is now available at https://v2.api2pdf.com -- the base route of our REST API. This is a more natural location for it and it is auto-generated from our source code. This means we do not have to maintain documentation in different spots and the default values that appear in the swagger spec are the exact default values our API uses if you do not specify those attributes in your payload.
It Wasn't All Sunshine and Rainbows
Given the scale of this overhaul, we were cautious about executing a full cutover. We know our API is used in ways we didn't anticipate, so our goal was to avoid forcing any code changes on your end unless absolutely necessary. The transition from the Azure Functions runtime to a proper .NET API inevitably brought side effects.
We conducted a slow rollout, starting with 5% of new traffic to the upgraded platform, then increasing to 10%. Reports of various issues started coming in from customers, and we quickly addressed each one. Some of the challenges we encountered included:
- Chrome 130 resulted in a 1-pixel difference compared to Chrome 121 for a customer—no resolution needed; the customer would need to adjust.
- A customer misused our
useCustomStorage
feature, and our new platform properly validated this scenario—an adjustment on their side was required. - Our platform was initially not accepting requests of type
application/text
, onlyapplication/json
. We made adjustments to be more flexible. - Some customers weren’t following standard values for advanced options on Wkhtml and Chrome. Since our platform previously worked with these improper values, we adjusted our system to continue supporting them as they were.
- Our new version did not output the Error attribute if there was no error, which led to confusion for some customers expecting to see the Error attribute with a null value. We made the necessary change.
- A minor programming error resulted in our new version outputting the result JSON in camelCase instead of the previous format (for v2), but we quickly rectified this.
As we resolved these issues, we steadily increased traffic routing until we reached 100%.
If you experienced any negative impacts during this rollout, we sincerely apologize. We believe that this upgrade will ultimately benefit everyone in the long run.
Summary
We now boast the best architecture, a simplified deployment scheme, greater reliability, more features and capabilities, and lower hosting costs.
It has been our honor to serve you all for the past six years, now with over 1,400 actively paying customers! We hope these major upgrades will support us well for the next six years!