Developers integrating SelectPdf into .NET projects often encounter unexpected delays during both compilation and runtime. Build times stretch from seconds to minutes as Visual Studio downloads and processes massive NuGet packages. Once deployed, HTML-to-PDF conversions that should complete instantly take 3 seconds on development machines and up to 3.5 minutes on production web servers. These performance characteristics impact developer productivity and end-user experience alike.
The Problem
SelectPdf delivers PDF generation capabilities through a NuGet package architecture that prioritizes feature completeness over build-time efficiency. The primary Select.Pdf package weighs in at 75.61 MB, while the .NET Core variant reaches 105.33 MB. When using the Blink rendering engine (Chromium-based), the package includes an entire Chromium browser folder that must be extracted and deployed with each build.
The runtime conversion performance presents separate concerns. Developers report consistent 3-second delays for simple HTML-to-PDF conversions on .NET Core, with some production environments experiencing conversions stretching to 3.5 minutes. These delays persist regardless of document complexity, indicating overhead in the conversion pipeline itself rather than rendering complexity.
The combination of slow builds and slow conversions creates compounding productivity losses. A developer making iterative changes to PDF output spends significant time waiting for builds to complete and conversions to finish, extending development cycles substantially.
Error Messages and Symptoms
Performance issues do not produce error messages in the traditional sense. Instead, developers observe:
Build time: 45 seconds (previously 12 seconds before adding SelectPdf)
Package restore: Downloading Select.Pdf.NetCore 25.2.0 (105.33 MB)
Conversion time: 3,000ms for single-page HTML document
On production servers, the symptoms become more severe:
Request timeout after 60 seconds
Conversion completed in 210,000ms (3.5 minutes)
Memory usage spike during conversion: 500MB+ for simple documents
Developers debugging performance often enable timing instrumentation:
var stopwatch = Stopwatch.StartNew();
var doc = converter.ConvertHtmlString(html);
stopwatch.Stop();
Console.WriteLine($"Conversion time: {stopwatch.ElapsedMilliseconds}ms");
// Output: Conversion time: 3247ms (simple HTML document)
Who Is Affected
SelectPdf performance issues impact several categories of developers and deployment scenarios:
Development Environment Impact:
- Teams using CI/CD pipelines experience extended build times
- Developers on slower machines face compounded delays
- Projects with frequent build-test cycles suffer productivity losses
- Cold builds after cache clearing take significantly longer
Runtime Performance Impact:
- Web applications generating PDFs synchronously
- Batch processing systems creating multiple documents
- Report generation features where users wait for PDF output
- High-traffic applications where conversion latency affects throughput
Deployment Scenarios:
- Docker containers with SelectPdf experience large image sizes
- Azure App Service deployments require Basic tier or higher
- Serverless functions face cold start penalties
- Kubernetes pods with memory limits may hit constraints
Evidence from the Developer Community
Performance complaints about SelectPdf appear across multiple platforms, with consistent themes around build impact and conversion speed.
Timeline
| Date | Event | Source |
|---|---|---|
| 2016-06 | Bubble.io users report "really really slow" export | Bubble Forum |
| 2019-06 | GitHub issue opened: "Converting html to pdf takes 3 seconds" | GitHub |
| 2020-07 | PDF.js issue reports slow rendering of SelectPdf output | Mozilla GitHub |
| 2021-12 | Large data issues and out of memory reports | GitHub |
| 2025-01 | Issue remains open, no resolution provided | - |
Community Reports
"I like SelectPDF very much, but it takes 3 seconds to convert html to pdf on .NET Core 2.1"
-- Developer, GitHub Issue #7, June 2019
The GitHub issue remains open, with the SelectPdf team responding that performance can be improved by disabling various features, but not providing a fundamental fix for the baseline conversion overhead.
"It takes 3 seconds to convert html to pdf on .NET Core... The same conversion takes about 3.5 minutes on the web server."
-- Stack Overflow discussion, cited in multiple forums
This disparity between local development performance and production server performance indicates environmental factors compound the base performance issues.
On the Bubble.io forum, users running SelectPdf through an integration plugin described the export process as "really really slow" for invoice generation, with the thread spanning multiple pages of developers sharing similar experiences.
Package Size Analysis
The NuGet package sizes directly impact build performance:
| Package | Version | Size |
|---|---|---|
| Select.Pdf | 25.2.0 | 75.61 MB |
| Select.Pdf.NetCore | 25.2.0 | 105.33 MB |
| Select.HtmlToPdf | 25.2.0 | 65.97 MB |
| Select.Pdf.x64 | 19.1.0 | 83.99 MB |
| Select.Pdf.NetCore.Blink | 25.2.0 | Additional Chromium folder |
For comparison, typical .NET NuGet packages range from 100 KB to 5 MB. SelectPdf packages are 15-100 times larger than average.
Root Cause Analysis
SelectPdf's performance characteristics stem from its architectural design decisions:
Package Size Contributors:
Multiple Rendering Engines: SelectPdf includes both WebKit and Blink (Chromium) rendering engines. Each engine requires substantial native binaries.
Bundled Dependencies: The Select.Html.dep and Select.Tools.dep files contain the actual rendering logic and must be deployed alongside the main assembly.
Chromium Inclusion: When using the Blink engine (required for modern HTML/CSS support), the package includes a full Chromium-124.0.6367.201 folder with browser binaries.
Cross-Platform Support Overhead: The .NET Core package includes binaries for multiple architectures, inflating the package size.
Conversion Speed Contributors:
Process Spawning: SelectPdf spawns external processes (Select.Html.dep) for each conversion, adding process creation overhead.
Engine Initialization: Each conversion may reinitialize the rendering engine, particularly in serverless or containerized environments without warm instances.
Default Configuration: The default settings enable JavaScript, plugins, and other features that add processing time even when not needed.
Memory Management: Developers report that memory is not efficiently released between conversions, leading to garbage collection pauses that affect subsequent operations.
Server Environment Factors:
Production servers often perform worse than development machines due to:
- Reduced CPU allocation in shared hosting
- Memory pressure from concurrent operations
- Cold starts in containerized deployments
- Azure App Service sandbox restrictions (requiring restricted rendering engine)
Attempted Workarounds
The SelectPdf documentation and community suggest several performance optimization approaches.
Workaround 1: Disable Unnecessary Features
Approach: Reduce conversion overhead by disabling features not required for the specific use case.
var converter = new HtmlToPdf();
// Disable JavaScript if not needed
converter.Options.JavaScriptEnabled = false;
// Disable image compression processing
converter.Options.JpegCompressionEnabled = false;
// Skip font embedding
converter.Options.EmbedFonts = false;
// Disable plugins
converter.Options.PluginsEnabled = false;
// Set minimum page load time to zero
converter.Options.MinPageLoadTime = 0;
// Use fastest compression
converter.Options.PdfCompressionLevel = PdfCompressionLevel.NoCompression;
Limitations:
- Disabling JavaScript breaks dynamic content
- No compression increases file sizes
- Feature stripping may not address core process overhead
- Reported improvements are modest (10-30% reduction, not elimination)
Workaround 2: Switch to Blink Rendering Engine
Approach: Use the Chromium-based Blink engine instead of WebKit.
converter.Options.RenderingEngine = RenderingEngine.Blink;
Limitations:
- Blink packages are even larger, increasing build times
- Requires .NET Framework 4.6.1+ or .NET Core
- Some SelectPdf features unavailable with Blink (bookmarks, post data, partial rendering)
- Does not address the fundamental 3-second baseline delay
Workaround 3: Font Caching Configuration
Approach: Configure font caching to use filesystem instead of memory.
Limitations:
- Helps in specific scenarios where font loading is the bottleneck
- Does not address core conversion overhead
- Requires writable filesystem access, complicating containerized deployments
Workaround 4: Increase Timeouts
Approach: Extend timeout settings to prevent failures on slow conversions.
converter.Options.MaxPageLoadTime = 120; // 120 seconds timeout
Limitations:
- Does not improve performance, only prevents timeout errors
- Users still experience the full delay
- Ties up server resources during extended conversions
- Masks the underlying performance problem
A Different Approach: IronPDF
IronPDF's architecture prioritizes conversion speed through a different technical approach. Rather than spawning external processes and initializing rendering engines per-conversion, IronPDF maintains a managed Chromium instance that handles conversions with minimal overhead.
Why IronPDF Performs Differently
The architectural differences that affect performance:
Managed Chromium Instance: IronPDF manages the Chromium rendering engine lifecycle, avoiding repeated initialization costs.
Direct Integration: Conversions occur within the .NET process rather than through inter-process communication with external executables.
Optimized Binaries: Platform-specific native components are loaded once and reused across conversions.
Streaming Architecture: Large documents can be processed without loading entirely into memory.
Performance testing in independent comparisons shows sub-second conversion for standard web pages, compared to SelectPdf's 2-3 second baseline.
Code Example
using IronPdf;
using System.Diagnostics;
/// <summary>
/// Demonstrates high-performance HTML to PDF conversion.
/// IronPDF's ChromePdfRenderer maintains an optimized rendering context
/// that avoids the per-conversion initialization overhead.
/// </summary>
public class HighPerformancePdfGenerator
{
private readonly ChromePdfRenderer _renderer;
public HighPerformancePdfGenerator()
{
// Renderer initialization happens once
// Subsequent conversions reuse the initialized context
_renderer = new ChromePdfRenderer();
// Configure rendering options
_renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.A4;
_renderer.RenderingOptions.MarginTop = 20;
_renderer.RenderingOptions.MarginBottom = 20;
}
public byte[] ConvertHtmlToPdf(string htmlContent)
{
// Conversion benefits from already-initialized renderer
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
return pdf.BinaryData;
}
public void ConvertWithTiming(string htmlContent, string outputPath)
{
var stopwatch = Stopwatch.StartNew();
var pdf = _renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs(outputPath);
stopwatch.Stop();
Console.WriteLine($"Conversion completed in {stopwatch.ElapsedMilliseconds}ms");
// Typical output: Conversion completed in 247ms
}
}
Key points about this code:
- The
ChromePdfRendererinstance can be reused across multiple conversions - Initialization cost is paid once, not per-conversion
- Memory management is handled within the .NET runtime
- No external process spawning required
Batch Processing Example
using IronPdf;
using System.Collections.Generic;
using System.Threading.Tasks;
/// <summary>
/// Demonstrates efficient batch PDF generation.
/// IronPDF supports parallel conversions without the process-spawning
/// overhead that limits SelectPdf batch performance.
/// </summary>
public class BatchPdfProcessor
{
public async Task<List<byte[]>> ProcessBatchAsync(List<string> htmlDocuments)
{
var renderer = new ChromePdfRenderer();
var results = new List<byte[]>();
// Process documents with efficient resource utilization
foreach (var html in htmlDocuments)
{
var pdf = renderer.RenderHtmlAsPdf(html);
results.Add(pdf.BinaryData);
}
return results;
}
public async Task ProcessLargeVolumeAsync(IEnumerable<string> htmlDocuments)
{
var renderer = new ChromePdfRenderer();
// For high-volume scenarios, IronPDF supports streaming output
foreach (var html in htmlDocuments)
{
var pdf = renderer.RenderHtmlAsPdf(html);
// Stream directly to storage without holding all PDFs in memory
using (var stream = pdf.Stream)
{
// Write to file system, blob storage, or other destination
await SaveToStorageAsync(stream);
}
}
}
private async Task SaveToStorageAsync(System.IO.Stream pdfStream)
{
// Implementation depends on storage destination
}
}
API Reference
For comprehensive documentation on performance optimization:
Migration Considerations
Licensing
IronPDF uses a commercial license model:
- Free development and testing with watermark
- Lite license starts at $749 (perpetual)
- Higher tiers available for multiple projects and enterprise needs
- Pricing details
SelectPdf also uses commercial licensing, with the Community Edition limited to 5 pages per document.
API Differences
The migration requires updating class names and method calls:
SelectPdf:
var converter = new HtmlToPdf();
converter.Options.PdfPageSize = PdfPageSize.A4;
converter.Options.JavaScriptEnabled = false;
var doc = converter.ConvertHtmlString(html);
doc.Save("output.pdf");
IronPDF:
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.EnableJavaScript = false;
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
| SelectPdf | IronPDF |
|---|---|
HtmlToPdf |
ChromePdfRenderer |
ConvertHtmlString() |
RenderHtmlAsPdf() |
ConvertUrl() |
RenderUrlAsPdf() |
Options.PdfPageSize |
RenderingOptions.PaperSize |
doc.Save() |
pdf.SaveAs() |
What You Gain
- Sub-second conversion times for typical documents
- Reduced build times (smaller package footprint relative to features)
- Consistent performance between development and production
- Cross-platform support (Windows, Linux, macOS)
- Docker and Azure compatibility without workarounds
What to Consider
- Commercial license required for production
- IronPDF package sizes are also substantial due to embedded Chromium
- Memory usage patterns differ; evaluate for your specific workload
- Initial renderer instantiation has a one-time cost
Conclusion
SelectPdf's 75-105 MB NuGet packages extend build times, and its process-spawning architecture introduces 3+ second conversion delays that can reach 3.5 minutes on production servers. While workarounds involving feature disabling provide marginal improvements, they do not address the fundamental architectural overhead. IronPDF's managed Chromium approach delivers sub-second conversions and avoids the repeated initialization costs that characterize SelectPdf's performance profile.
Jacob Mellor has spent 25+ years building developer tools, including IronPDF.
References
- Converting html to pdf takes 3 seconds - GitHub Issue #7{:rel="nofollow"} - Original performance report on SelectPdf GitHub
- Selectpdf really slow when exporting to PDF - Bubble Forum{:rel="nofollow"} - Community discussion of export performance
- PDFs generated by selectpdf.com slow to render - Mozilla pdf.js Issue #12098{:rel="nofollow"} - Report on SelectPdf output rendering performance
- Large data Issue using SelectPdf - GitHub Issue #22{:rel="nofollow"} - Memory and performance issues with large documents
- SelectPdf Troubleshooting{:rel="nofollow"} - Official troubleshooting documentation
- SelectPdf Conversion Delay{:rel="nofollow"} - Official documentation on timeout configuration
- NuGet Gallery - Select.Pdf{:rel="nofollow"} - Package size and version information
- NuGet Gallery - Select.Pdf.NetCore{:rel="nofollow"} - .NET Core package information
For the latest IronPDF documentation and tutorials, visit ironpdf.com.
Top comments (0)