Skip to main content
Back to Blog

Worked example: testing a 5 MB PDF upload limit byte by byte

Written by Ankur Prajapati

Published 2026-06-01

LinkedIn profile
Advertisement

Note: this is a composite, illustrative scenario, not a report about a specific company or incident. It combines failure patterns that are common in upload pipelines so we can show the testing method end to end. The byte numbers are real arithmetic; the system is hypothetical.

The setup

Example scenario: a document portal says "PDFs up to 5 MB". Users occasionally report failures with files near the limit, but support cannot reproduce them, because the files they receive in tickets have been through email and are no longer the same bytes.

The first step is to stop using "whatever PDF is handy" and switch to deterministic fixtures: same type, same template, three exact sizes around the limit. Assuming the limit is 5 MiB:

  • 5,242,879 bytes (one under)
  • 5,242,880 bytes (exactly at the limit)
  • 5,242,881 bytes (one over)

All three can be produced from the 5 MB PDF preset or from explicit links such as /generator?ext=pdf&bytes=5242881. Because the generator runs in the browser and the link fixes type and size, everyone on the team gets identical files.

The test procedure

  1. Record each file's size and SHA-256 locally (wc -c, sha256sum).
  2. Upload each file through the same path production uses (same CDN, gateway and services), first unthrottled, then with a slow network profile so that timeout behaviour can be observed separately from size validation.
  3. For every attempt, log the request's Content-Length, the HTTP status, the error message the user sees, and, for accepted files, the stored object's size and hash.
  4. Compare the results with an expected-results table written before the test.

A quick way to do step 3 for the API layer, independent of the UI:

for f in under-5242879.pdf exact-5242880.pdf over-5242881.pdf; do
  printf '%s  ' "$f"
  curl -s -o /dev/null -w '%{http_code}\n' \
    -F "file=@$f;type=application/pdf" \
    https://staging.example.test/api/upload
done

What this kind of test typically finds

In this scenario, two problems show up, both of which we have seen variations of in real pipelines.

Silent truncation. The "exact" file is accepted with a 200, but the stored object is 5,242,368 bytes, 512 bytes short. The hypothetical cause: a media optimisation service sits in the upload path for all files, treats the PDF as generic binary, runs a "normalise" step, and writes back a buffer that drops the trailing bytes. The gateway reports success because the downstream call succeeded. Nobody notices, because nobody compares sizes after upload. For a PDF, losing trailing bytes is serious: readers locate the cross-reference table from the end of the file, so the document may fail to open or need repair.

An unhelpful rejection. The "over" file is rejected, but the user sees a generic "Upload failed" message, identical to what they would see on a network error. Users retry, fail again, and open a ticket.

Fixes that address those findings

  • Route files to post-processing by verified type; skip optimisation for application/pdf unless it is explicitly requested.
  • After storing, compare the declared size with the stored size (and ideally a hash) and alert on any difference for non-streaming uploads.
  • Return a structured error such as {"code": "FILE_TOO_LARGE", "max": 5242880} with status 413, and show "Maximum file size is 5 MB" in the UI.
  • Validate size in the browser before uploading, so users do not wait for a long upload only to be rejected, and keep the server-side check as the authority.

Takeaways

Boundary testing is not "upload a big PDF from the Downloads folder". It needs exact byte counts, an expected-results table, and a check on what was actually stored, not just the status code. Keep the fixture links in the test plan and re-run the three-file matrix whenever anything in the storage pipeline changes.

Related: the 5 MB PDF upload boundary scenario and the file upload testing guide.

Advertisement