A PDF Tool Is Also an Engine Choice

In Stirling PDF, an operation's availability depends on more than whether its interface appears in the editor. The current focus is the chain between a visible tool, the provider that implements it, the resources that provider needs, and the output it can produce. Understanding that chain lets a reader diagnose a missing or degraded feature by asking which engine is enabled, which alternative is available, what data or binaries are required, and what the operation promises to return.

This is a natural consequence of the platform's scope. Stirling PDF is not built around one universal PDF algorithm. Its documented stack combines a Java/Spring Boot application and PDFBox with specialist tools such as LibreOffice, qpdf, Tesseract, OCRmyPDF, Ghostscript, ImageMagick, and WeasyPrint. The result is more flexible than a single-engine utility, but it also means that the environment becomes part of the product.

The core path and the specialist paths

A useful way to understand the engine model is to separate the application from the providers it can call. The documented backend uses PDFBox for core PDF operations. Around that core, other providers cover jobs that require a different document model or a different kind of transformation. LibreOffice supports office-document conversion paths. qpdf is associated with PDF optimization and repair. Tesseract and OCRmyPDF support OCR. WeasyPrint and other tools contribute to document-generation or conversion paths.

This does not mean that each operation is permanently assigned to one binary. The repository's endpoint configuration groups operations by provider and records alternatives. Repair can be associated with qpdf or Ghostscript. Compression can have qpdf, Ghostscript, or Java options. OCR can use Tesseract or OCRmyPDF. File-to-PDF conversion can use LibreOffice or Unoconvert. The platform is therefore not just a set of adapters; it has a capability-selection layer that asks whether at least one suitable provider is available.

That layer matters because a missing dependency should not necessarily make the whole application unusable. If a server has no LibreOffice installation, a file-to-PDF endpoint may be unavailable while merge, rotation, or metadata operations continue to work through the Java path. If an operation has alternatives, the endpoint may remain available through another provider. The application can degrade selectively rather than presenting one undifferentiated “installed” or “broken” state.

Selective degradation is useful, but it has a limit. An alternative provider is not evidence of identical results. Two engines may accept the same input and produce a file that is technically valid while differing in layout fidelity, performance, metadata handling, or support for edge cases. The repository documents the relationship between operations and providers; it does not provide a benchmark that ranks the alternatives. A deployment should therefore treat “enabled” as an availability fact, not as a quality guarantee.

The same reasoning applies to the Docker variants. The ultra-lite compose example disables additional features, removes a group of CLI-related endpoints, and uses a smaller example memory limit. The standard example includes a broader embedded setup. The fat example enables additional features, gives the container a larger example memory limit, and assigns a larger memory budget. These variants are operating points: they trade image size, feature coverage, resource needs, and operational complexity. They are not a universal ladder in which the largest image must always produce the best result.

The resource numbers in the compose examples illustrate the point but should not be mistaken for immutable product limits. A deployment can change environment variables, ports, volumes, and resource policies. What the examples make clear is the dependency relationship: a tool bundle affects what the service can expose, and a resource budget affects what it can handle reliably. The configuration is part of the feature's meaning.

Why capability has to be visible at runtime

A static feature list is inadequate for a platform with optional engines. Endpoint configuration checks explicit disables, functional groups, and provider alternatives. An operation can be disabled directly, disabled because its only provider group is unavailable, or kept enabled because another supported group remains active. This turns the environment into a decision input.

For a user, the practical symptom may be simple: a button is missing, a conversion is unavailable, or a pipeline step refuses to run. The underlying causes differ. A missing tool, a disabled group, an unsupported image variant, an absent language pack, or a configuration choice can all produce a similar surface symptom. Diagnosing the cause requires following the provider relationship rather than repeatedly retrying the operation.

A good operational check asks four questions:

  1. What provider implements the operation? The endpoint may belong to a Java path, a command-line tool, a Python-backed path, or several alternatives.
  2. Is that provider enabled in this image and configuration? The endpoint configuration and deployment flavor can expose different capabilities.
  3. What resources does the provider need? A binary alone may not be enough; language data, fonts, temporary space, or a suitable memory budget may also matter.
  4. What output does the operation promise? A result may be a PDF, a different document type, a report, or an archive containing multiple artifacts.

These questions are more useful than asking whether Stirling PDF “supports” a feature in the abstract. Support has at least three layers: the code may define an endpoint, the deployment may enable a provider, and the input may still fail because the required data or conditions are absent.

OCR as a worked example

OCR makes the engine boundary visible because it combines a provider, language resources, validation, temporary processing, and a parameter-dependent output. The OCR endpoint requires the caller to select at least one language. It looks in the configured tessdata directory, filters the request against the language files that are actually available, and rejects the request if no selected language can be used. This prevents a request from silently proceeding with a language model the installation does not have.

The endpoint configuration distinguishes two OCR provider groups: OCRmyPDF and Tesseract. The endpoint uses OCRmyPDF when that provider is enabled and otherwise has a Tesseract path. The important operational insight is not which name is preferred. It is that the same user-facing OCR function has a provider decision before the pages are transformed. Installing the application without installing or enabling the expected OCR path is not enough.

The language data is another boundary. The OCR guide explains that Tesseract language packs come in different families, including smaller and faster packs and larger packs aimed at better recognition quality. Stirling PDF uses a fast English pack by default in the documented setup, and additional .traineddata files can be mounted into the configured tessdata directory in Docker. The chosen pack affects load size and the possible accuracy trade-off, but the repository does not provide a Stirling-specific accuracy benchmark. The safe conclusion is that the pack choice is a deployment decision, not that one family will always be better for every document.

The output can change with a parameter as well. In the ordinary path, the endpoint declares a PDF result. When the caller requests a sidecar, the declared output becomes a ZIP with a single output that contains the related artifacts. That distinction is important for composition. A later operation that expects a PDF cannot treat the sidecar response as if it were still an ordinary PDF without handling the archive boundary.

A typical OCR request therefore passes through several conditions. The caller supplies a file and languages. The endpoint validates the render mode and language availability. Configuration determines which OCR provider is used. The provider processes the temporary input, and the endpoint returns either a PDF result or the sidecar form. A failure can occur before recognition begins if the language data is absent; it can occur during provider execution; or it can appear later when another step misunderstands the output shape.

That sequence also explains why “install OCR” is an incomplete deployment instruction. An operator has to decide which languages the workflow promises to handle, place the corresponding data where the service can read it, and preserve that data when a container is recreated. The service may start successfully while a requested language remains unavailable. In that case the failure is not a general outage: it is a mismatch between the workflow's language requirement and the resources attached to the running instance.

The provider choice creates a second form of mismatch. OCRmyPDF and Tesseract are both recognized paths, but the source does not say that they produce identical layouts, metadata, or performance. A test that succeeds with one provider does not automatically validate the other. If a lightweight deployment falls back to a different path, the team should test representative scans again rather than treating the alternative as a transparent replacement. This is especially important when the output enters a later pipeline step that depends on searchable text, page geometry, or a particular file shape.

The sidecar option makes the boundary visible even when recognition succeeds. A standard searchable PDF can proceed to a later PDF operation. A ZIP containing a PDF and text sidecar is a packaged result that needs an explicit unpacking or selection decision before the next step. In other words, output shape is part of the feature contract. An operation can be available, complete successfully, and still be unsuitable for the next stage if the workflow has not accounted for the selected output mode.

sequenceDiagram participant U as Caller participant C as OCR endpoint participant L as Language data participant G as Provider configuration participant O as OCR engine U->>C: Submit PDF and selected languages C->>L: Check requested language files alt No usable language L-->>C: Validation failure C-->>U: Reject request else Languages available L-->>C: Valid language set C->>G: Select enabled OCR provider G-->>C: OCRmyPDF or Tesseract C->>O: Process temporary input O-->>C: Recognized document alt Sidecar requested C-->>U: ZIP with PDF and sidecar output else Standard output C-->>U: Searchable PDF end end

The diagram shows why OCR is more than “turn images into text.” The result depends on an input condition, a resource condition, a provider condition, and an output condition. Each is a potential control boundary for a pipeline or deployment.

Image variants are operating choices

The ultra-lite, standard, and fat variants make the same engine logic visible at the packaging level. An ultra-lite deployment is appropriate when a smaller capability surface and lower example memory budget matter more than having every additional feature. A fat deployment is appropriate when broader provider coverage and prebundled resources justify a larger image and a higher resource budget. The standard variant occupies a middle position in the documented examples.

The choice should follow the workflow rather than the label. A team that only merges, rotates, and rearranges PDFs may not benefit from carrying every conversion and OCR dependency. A team that receives scanned documents in several languages may value an image with the required OCR path and language volumes already planned. A service that converts office files needs to test the LibreOffice path, not merely confirm that the web UI loads.

There is also a maintenance cost. More providers increase the number of binaries, language packs, fonts, temporary-file behaviors, and update paths that an operator must understand. Fewer providers reduce that surface but can make particular operations unavailable. The right target is not maximum feature count; it is sufficient capability under a known resource and maintenance budget.

The source's development documentation reinforces this point by distinguishing local testing from full Docker testing. A local Java or UI run does not include features that depend on external tools such as qpdf, LibreOffice, or Python scripts. Those integrations need verification in an environment that actually contains them. A button can render correctly while its provider path remains untested.

What the repository does not tell us

The engine configuration tells us which alternatives are recognized, not which alternative will give the best result on a particular document. It does not quantify OCR accuracy, conversion fidelity, throughput, memory consumption, or the rate of failures across real workloads. Those are important engineering questions, but they require representative documents and measurements outside the repository's descriptive evidence.

Nor should provider presence be confused with operational readiness. A Tesseract binary without the needed language data is not a usable OCR deployment for that language. A conversion engine without the expected fonts may produce a valid but visually different document. A container with a nominal memory limit may still need testing under the largest files and the highest concurrency the workflow allows. The platform's configuration can expose a capability; it cannot substitute for workload testing.

This is where the boundary-of-control idea becomes practical. A deployment owner should record not only which Stirling PDF image is running, but also which provider groups are enabled, which language or conversion resources are mounted, what output shapes are expected, and which operations have been tested end to end. That record turns an accidental environment into an intentional one.

The final implication is architectural. Once operations can use different engines and return different shapes, a pipeline cannot safely connect them by name alone. It needs a shared description of accepted formats, produced formats, and the number of files entering or leaving each step. In Stirling PDF, that contract is the bridge from a configurable collection of tools to composable automation.

References