Short answer: compress a PDF archive's access copies, but store signed originals unchanged. Storage cost matters; signature fidelity decides which bytes are authoritative. For server-side logistics contracts, template ownership decides who can approve a change to the document before signing; archive ownership decides who can prove what was signed afterward. Those are different jobs.
| Archive choice | What stays authoritative | Best fit | Main constraint |
|---|---|---|---|
| Signed original plus compressed access copy | Signed original and linked audit evidence | Signed freight agreements subject to later dispute | Retain and govern two objects |
| Signed original only | Signed original and linked audit evidence | Small archives or strict evidentiary requirements | More bytes served for routine viewing |
| Compressed replacement only | Transformed file | Unsigned, reproducible reading material | Cannot assume the prior signature still verifies |
The default for a signed contract is the first row. The second is a sensible runner-up if a second copy would add more operational work than it saves. The last row does not belong in the signed-record path without a legal and technical validation specific to that transformation. A smaller file is not evidence of equivalent bytes.
Bytes matter.
Who owns the template at signing time?
A carrier contract can start from a centrally approved template, pick up a lane schedule, and then collect signatures. Keep those stages distinct. The template owner should approve the version and its variable fields before the signing service renders a specific agreement. The signing workflow should bind the final document to its signers and evidence. The archive then stores the exact signed artifact, its digest, the approved template version identifier, and a pointer to the audit trail. A template identifier alone cannot reconstruct a negotiated contract if the actual signed bytes have been discarded.
Consider the difference between correcting a lane schedule before anyone signs and quietly changing that schedule in a stored copy after execution. The first is a template or transaction review. The second creates a new artifact, even if the rendered page looks familiar. Record the approved template revision and actual variables so reviewers can explain how a contract was generated; retain the executed PDF so they can inspect what the parties signed. Do not promise that replaying today's renderer against yesterday's template will reproduce the signed file byte for byte.
This is the first decision criterion: can the team reproduce the unsigned input and identify who authorized each template revision? If operations can silently edit clause text after legal approval, shaving storage is the wrong optimization. Make approval and signing separate permissions. A new template revision should affect future agreements, never overwrite an executed one.
The second criterion is stricter: what does verification actually cover? PDF signatures rely on byte ranges, and an incremental update can append changes after a signed revision. A visual match between two pages does not establish that they contain the same signed bytes or that later changes are acceptable. PDF/A is useful for long-term visual preservation, but conformance to an archival profile does not, by itself, prove a signature or preserve a complete transaction history. Validate the exact artifact and its signature state at intake, retain the original, and treat any derived PDF as a different object.
Should we compress the PDF archive or store signed originals?
Not by default. Recompressing embedded images, rewriting object streams, or regenerating pages changes bytes; an existing PDF signature cannot be assumed to cover the replacement. Even a lossless transformation at the image level may rewrite the enclosing PDF. Render comparisons can catch legibility damage, but they cannot substitute for cryptographic verification or an audit trail.
Keep both roles separate.
Keep the chain easy to inspect. A manifest for one shipment agreement might record a stable contract ID, template revision, signer workflow ID, creation time, cryptographic digest of the signed bytes, storage key for the original, and a separate key and digest for a preview. Those IDs are internal examples, not claims about any signing provider. Store audit evidence alongside the record with an explicit retention policy; an image of a signature is not a complete signing history. Access controls should prevent a preview-generation job from modifying the original.
Here is the write boundary in TypeScript. The storage and verification interfaces deliberately leave room for local or hosted implementations; the important detail is that preview generation reads the immutable original and writes a new key.
import { createHash } from 'node:crypto';
type Store = {
putIfAbsent(key: string, bytes: Uint8Array): Promise<void>;
};
type Verifier = {
verify(bytes: Uint8Array): Promise<{ valid: boolean; report: Uint8Array }>;
};
type Compressor = {
makePreview(bytes: Uint8Array): Promise<Uint8Array>;
};
const sha256 = (bytes: Uint8Array) =>
createHash('sha256').update(bytes).digest('hex');
async function archiveAgreement(
contractId: string,
signedPdf: Uint8Array,
store: Store,
verifier: Verifier,
compressor: Compressor,
) {
const result = await verifier.verify(signedPdf);
if (!result.valid) throw new Error('Signature verification failed');
const originalDigest = sha256(signedPdf);
const originalKey = `contracts/${contractId}/original-${originalDigest}.pdf`;
const evidenceKey = `contracts/${contractId}/verification-${originalDigest}.bin`;
await store.putIfAbsent(originalKey, signedPdf);
await store.putIfAbsent(evidenceKey, result.report);
const preview = await compressor.makePreview(signedPdf);
const previewDigest = sha256(preview);
const previewKey = `contracts/${contractId}/preview-${previewDigest}.pdf`;
await store.putIfAbsent(previewKey, preview);
return { originalKey, originalDigest, evidenceKey, previewKey, previewDigest };
}
The snippet does not make the three writes atomic. Publish the manifest only after all required writes succeed; on retry, verify the digests and reuse existing immutable objects. A failed preview should not erase a successfully stored original. The verifier also needs a documented trust policy for certificate chains, revocation material, timestamps, and allowed post-signing changes; a single boolean is an intentionally narrow interface, not a complete validation policy.
What should the archive test before rollout?
Build a corpus that includes signed and unsigned agreements, scanned attachments, vector schedules, multiple revisions, and PDFs with permitted and unexpected changes after signing. Compare rendered pages of each preview against its source at fixed settings, then inspect text extraction, form fields, annotations, and attachment handling separately. Page images alone miss searchable text and embedded data. Track size distributions, not a cherry-picked average: record original bytes, preview bytes, generation time, and any validation failures for each corpus category. Benchmark the actual transport and retrieval path as well as stored bytes; the bottleneck may be repeated downloads or preview CPU rather than capacity.
On deployment, make original writes immutable and audit reads and retention changes. Log contract ID, template revision, digests, job ID, and verifier outcome without dumping contract contents. Alert on verification failures and on a manifest that references a missing original. Re-run reads against sampled archived records and compare digests. Storage lifecycle rules must account for retention and legal holds before any deletion is enabled.
There is a real cost trade-off: two objects mean more storage and more bookkeeping. Estimate it from the measured corpus and expected reads, including request counts, transfer, preview compute, backup, and retention duration. Do not infer savings from a compressed sample or assume all signed files compress equally.
When is the runner-up better?
Keep only the signed original when most contracts are retrieved rarely, the corpus barely compresses, or the team cannot maintain separate access-copy and record-of-authority policies. An on-demand renderer may be enough, provided it never replaces the original and its output is clearly identified as a derivative. This keeps template ownership, signature validation, and archival authority legible with fewer moving parts.
For signed freight contracts, the governing rule remains straightforward: choose the approved template before execution, verify and preserve the signed bytes after execution, and measure whether a derivative earns its operational cost. Compression is a delivery decision, not a way to revise the record.
References
- ISO 32000-2, Portable Document Format: https://www.iso.org/standard/75839.html
- RFC 5652, Cryptographic Message Syntax: https://www.rfc-editor.org/rfc/rfc5652
- RFC 3161, Time-Stamp Protocol: https://www.rfc-editor.org/rfc/rfc3161
- ISO 19005-4, PDF/A-4 long-term preservation: https://www.iso.org/standard/71832.html
- NIST FIPS 180-4, Secure Hash Standard: https://doi.org/10.6028/NIST.FIPS.180-4
Top comments (0)