Home/Resources/Fix Buffering & Ad Revenue with SCTE-35 + MediaTailor

How to Fix Buffering & Improve Ad Revenue with Proper SCTE-35 + MediaTailor

The most common SCTE-35 cue and AWS MediaTailor misconfigurations that cause buffering at ad breaks and silently depress fill rate — and how to fix each one.

Buffering at ad breaks and unexplained ad fill-rate loss on AWS MediaTailor streams almost always trace back to a handful of SCTE-35 cue-signaling misconfigurations upstream of MediaTailor itself — not a MediaTailor bug. This guide covers the five most common causes and how to fix each one.

Most "MediaTailor is buffering" tickets aren't a MediaTailor problem at all — they're an upstream signaling problem that MediaTailor is simply exposing. Here's how the pieces fit together, then the specific misconfigurations to check, in the order they're worth checking.

How SCTE-35 and MediaTailor Work Together

SCTE-35
A cue-message standard that live encoders embed in the transport stream to mark where an ad break should start and how long it should last — the signal that tells downstream systems "an ad break happens here."

Your live encoder embeds SCTE-35 cue messages in the transport stream. AWS MediaTailor reads these cues from the packaged HLS/DASH manifest, calls your ad decision server (ADS) for creative, and stitches the returned ad segments into the manifest at the cue point. If any link in that chain is misconfigured, you get either a stall in playback or an empty (no-fill) ad break.

Cause 1: Splice Points Not Aligned to Segment Boundaries

If the encoder's SCTE-35 pts_time doesn't line up with a keyframe/segment boundary, the packager has to cut mid-GOP to honor it. That forces an extra encode or a segment re-cut at the edge, which is what viewers experience as a stall right as the ad break starts.

Fix: configure the encoder (e.g. AWS Elemental MediaLive) to snap ad markers to the nearest segment boundary, and keep segment duration consistent between content and ad-break segments.

Cause 2: Mixing splice_insert and time_signal Commands

Older encoder presets emit the simpler splice_insert command; most current MediaTailor configurations expect time_signal with a segmentation_descriptor for accurate break type and duration. Mixing both inconsistently across your channel lineup causes some breaks to be read correctly and others to be dropped or misinterpreted.

Fix: standardize every live channel on time_signal + segmentation_descriptor, and verify with a cue-level manifest inspection tool rather than assuming encoder defaults are correct.

Cause 3: Ad Break Duration Mismatch

If the SCTE-35 cue declares a 30-second break but your ad decision server returns 15 seconds of creative, MediaTailor fills the remaining 15 seconds with slate or filler — which looks like a fill rate problem in reporting even though the ADS did return an ad. This is one of the most common causes of "fill rate looks lower than our ad server's numbers" discrepancies.

Fix: make sure break duration signaled by SCTE-35 matches what your ADS is configured to fill, and monitor MediaTailor's FillRate/AdDecisionServerFillErrors CloudWatch metrics against your ad server's own numbers to catch the gap.

Cause 4: Malformed or Incomplete ADS Targeting Parameters

MediaTailor passes viewer/session parameters to your ad decision server via macros in the ad tag URL. If required parameters are missing (device type, content genre, session ID) many ad servers return a no-fill response rather than an error — which is easy to miss unless you're specifically watching no-fill rate, not just error rate.

Fix: audit the ad tag macro configuration against what your ADS actually requires, and treat no-fill responses as a monitored metric, not just a side effect.

Cause 5: CDN Caching Ad Segments Incorrectly

Personalized or session-specific ad segments must not be cached the same way as content segments. If your CDN origin/cache policy treats ad manifest fragments as cacheable static content, viewers can receive stale or mismatched ad segments, causing playback errors that look like buffering.

Fix: set explicit cache-control headers for MediaTailor's personalized manifest and ad segment origin paths, distinct from your VOD/live content cache policy.

Quick Diagnostic Checklist

  • Do SCTE-35 cue pts_time values align with segment boundaries in the packaged manifest?
  • Is every channel using time_signal + segmentation_descriptor consistently?
  • Does the SCTE-35 break duration match what the ADS is configured to return?
  • Are ad tag macros complete for every required ADS targeting parameter?
  • Is the CDN cache policy for ad segments separated from content segment caching?

Frequently Asked Questions

Almost always because the SCTE-35 splice point does not align with a segment boundary, forcing the player or packager to cut mid-segment. This produces a discontinuity the player has to re-buffer around. Aligning your encoder's GOP/segment boundaries to the SCTE-35 cue's pts_time eliminates this.
The two most common causes are an ad decision server returning no-fill because MediaTailor is sending incomplete or malformed targeting parameters, and slate/filler being served because the ad duration returned by the ADS doesn't match the SCTE-35 break duration. Both are visible in MediaTailor's CloudWatch metrics once the right dimensions are enabled.
splice_insert is the older, simpler command that directly signals an ad break start/end. time_signal paired with segmentation_descriptor is the modern, more flexible approach used by most current encoders and is what AWS MediaTailor expects for accurate ad break duration and type detection. Mixing the two inconsistently is a common source of dropped or malformed cues.
SCTE-35 cues are primarily a live and linear broadcast concept, carried in the transport stream from the encoder. For VOD, ad breaks are typically defined directly in the SSAI stitcher's configuration or via a separate ad markers file, not live SCTE-35 signaling.

Related Services

Seeing Buffering or Fill Rate Gaps in Production?

Get a hands-on SCTE-35 and MediaTailor configuration audit — most root causes are found within days.