Maximum Payload Size Limits for Chrome vs Firefox: Diagnostic & Configuration Guide

Exact Byte Thresholds & Encryption Overhead

The Web Push specification defines a theoretical 4096-byte maximum for encrypted payloads. In production, cryptographic expansion and engine-specific validation reduce this ceiling significantly. Chromium’s aes128gcm implementation introduces a fixed overhead of 49 bytes (32-byte salt, 16-byte authentication tag, and 1-byte padding delimiter) before plaintext data is processed. Firefox enforces stricter base64url encoding validation, which reduces the effective safe capacity to approximately 3980 bytes. Improper padding or boundary violations trigger divergent failure modes: Chrome explicitly returns 413 Payload Too Large, while Firefox frequently drops the message silently or returns a 400 Bad Request. For precise cryptographic expansion mechanics and encryption standards, consult the Push API Payload Encryption documentation.

Diagnostic Workflow: Identifying Silent Failures & 413 Errors

Isolate truncation points and endpoint rejections using this systematic validation sequence.

  1. Intercept Service Worker Events: Log raw ciphertext size before rendering to isolate client-side truncation.
self.addEventListener('push', (event) => {
const payloadSize = event.data ? event.data.byteLength : 0;
console.info(`[Push] Received ciphertext: ${payloadSize} bytes`);
if (payloadSize > 4047) {
console.warn('[Push] Payload exceeds Chromium safe threshold. Truncation or drop imminent.');
}
event.waitUntil(
self.registration.showNotification('System', { body: 'Payload boundary validated' })
);
});
  1. Validate Server-Side Headers: Ensure middleware logs the exact Content-Length of the encrypted ciphertext before dispatch. Mismatches between calculated and transmitted sizes indicate pre-encryption compression failures.
  2. Inspect Network Traffic: Filter DevTools Network tab for webpush requests. Extract the X-Request-ID from response headers to correlate with push provider logs and isolate routing failures.
  3. Cross-Reference Engine Responses:
  • Chrome: Explicit 413 Request Entity Too Large.
  • Firefox: 400 Bad Request (malformed padding) or silent drop (zero-byte delivery).
  1. Boundary Testing: Simulate exact thresholds using curl to capture engine-specific HTTP status codes.
# Generate a 4050-byte payload (expected 413 on Chrome, 400/silent on Firefox)
dd if=/dev/urandom bs=4050 count=1 2>/dev/null | base64 -w 0 > payload.bin
curl -v -X POST "https://fcm.googleapis.com/fcm/send/YOUR_ENDPOINT" \
-H "Authorization: Bearer <VAPID_TOKEN>" \
-H "TTL: 86400" \
-H "Content-Type: application/octet-stream" \
-H "Content-Encoding: aes128gcm" \
--data-binary @payload.bin

Configuration & Compression Strategies for Edge Cases

Enforce strict payload boundaries at the application layer to prevent delivery degradation during high-volume campaigns.

  • Pre-Encryption Validation: Implement UTF-8 byte counting and JSON minification. Guarantee all payloads remain under 3800 bytes before cryptographic operations.
  • Chunking Fallback: For payloads exceeding 3KB, implement sequential notification batching. Use unique tag identifiers to enable client-side deduplication and prevent user spam.
  • VAPID Alignment: Schedule VAPID key rotation alongside payload size audits. Signature bloat in the Authorization header can indirectly impact routing efficiency. Align server-side retry logic and fallback routing with foundational Core Protocols & Browser Implementation standards to maintain endpoint compliance and delivery reliability.

Cross-Browser Validation & Monitoring Setup

Deploy automated safeguards to detect regression and enforce compliance across user agents.

  • CI/CD Pipeline Integration: Integrate web-push library validators and custom pre-flight scripts to reject builds containing payloads >3800 bytes.
  • Fallback Telemetry: Correlate pushsubscriptionchange events with payload size thresholds. A spike in subscription invalidations often indicates silent truncation or cryptographic mismatch.
  • Error Code Matrix: Map engine-specific failures for rapid infrastructure triage. | Engine | Quota/Storage Error | Network/Abort Error | |--------|---------------------|---------------------| | Chrome | QuotaExceededError | NetworkError | | Firefox| InvalidStateError | AbortError |

Production Safe Limits Reference

Browser/Environment Safe Limit (Bytes) Recommended Production Cap
Chrome 115+ 4047 3800
Firefox 115+ 3980 3800
Android WebView 3900 3800

Step-by-Step Resolution Protocol

Execute this sequence to resolve payload truncation, enforce delivery compliance, and prevent subscription churn.

  1. Measure Raw Payload: Calculate exact UTF-8 byte length pre-encryption. const byteLength = new TextEncoder().encode(JSON.stringify(data)).length;
  2. Apply Cryptographic Expansion: Encrypt using aes128gcm and account for the mandatory +49 byte overhead.
  3. Encode & Verify: Base64url encode the ciphertext and validate against the 3980-byte absolute threshold.
  4. Compress or Split: If the payload exceeds 3980 bytes, compress with pako.deflateRaw() or split into a multi-notification sequence using unique tag identifiers.
  5. Dispatch & Monitor: Transmit with TTL: 86400 and required headers (Content-Length, Encryption, Crypto-Key, TTL). Monitor endpoint responses for 413 or 400 status codes.
  6. Implement Resilient Retries: Configure exponential backoff specifically for 413 responses. Do not retry malformed payloads without size reduction to prevent endpoint rate-limiting and subscription churn.