Engineering

A sane AWS video streaming architecture for 2026

Upload, transcode, package, deliver, authorise, observe. A practical HLS pipeline with S3, MediaConvert, CloudFront, signed access, and the cost traps.

ZX

Zynitex Engineering

Product & engineering notes

22 September 202612 min readUpdated 21 October 2026
Video engineering workstation with a landscape preview, encoding timeline, and compact server

The short answer

For most subscription video products, the sane AWS shape is: upload to a private S3 bucket, transcode with MediaConvert into HLS renditions, serve through CloudFront with Origin Access Control, and authorise playback with short-lived signed URLs or cookies. Keep the bucket private, use 4–6 second segments for VOD, and watch egress cost more closely than compute.

What this note covers

  • Video is a delivery product; the CDN and the bitrate ladder matter more than the upload form.
  • Use HLS with adaptive bitrate, not one large MP4.
  • Never make the S3 bucket public; use OAC and signed access.
  • Entitlement checks belong in your backend, not the player.
  • Egress, not transcoding, is usually the bill that grows.
On this page(11 sections)
  1. 01The job to be done
  2. 02The five-piece pipeline
  3. 03Why HLS, not a giant MP4
  4. 04A bitrate ladder that doesn’t waste money
  5. 05Keep the bucket private
  6. 06Authorisation belongs in your backend
  7. 07The cost that surprises people
  8. 08Monitor the pipeline, not just the player
  9. 09Operations checklist
  10. 10Where teams get it wrong
  11. 11Keep it boring

Video architecture attracts over-engineering. Most subscription catalogues don’t need a multi-region DRM platform on day one. They need a private bucket, a reliable transcoder, a CDN, and playback that starts quickly on a ₹12,000 phone.

We’ve run this shape for Raykulam and Shaligram Healing: S3 + MediaConvert + CloudFront, with EC2 auto scaling behind the application and CloudWatch around it. It’s not exotic. It’s boring in the way infrastructure should be.

The job to be done

Strip away the vendor names and a video platform has five jobs: accept an upload, process it into playable formats, store the output, deliver it close to the viewer, and decide who is allowed to watch. Everything else — recommendations, analytics, downloads — sits on top of those five.

Delivery pipelineIllustrative

S3 source

Private bucket

MediaConvert

HLS renditions

CloudFront

Edge cache + OAC

Player

Signed access

1080p720p480p360pCaptionsThumbnails
The pipeline: source, transcode, package, deliver, authorise.

The five-piece pipeline

StageAWS pieceWhat it doesFailure mode
UploadS3 with presigned multipart uploadAccepts large files without routing them through your appUploads through the web server; timeouts and memory spikes
ProcessMediaConvert jobCreates HLS renditions, thumbnails, and metadataStuck jobs, no retry, no visible status
StorePrivate S3 bucketsHolds masters and packaged outputA public bucket or an accidental ACL
DeliverCloudFront + OACCaches segments at the edge and terminates TLSDirect origin access or poor cache keys
AuthoriseBackend + signed URL/cookieChecks entitlement and grants short-lived accessSecrets in the browser or permanent public links
ObserveEventBridge, CloudWatch, alarmsJob status, errors, delivery health, costSilent failures discovered by customers

Why HLS, not a giant MP4

HLS splits video into short segments described by a manifest. The player picks a rendition that fits the current bandwidth. That means faster start, fewer stalls, and better mobile behaviour. It also lets the CDN cache segments instead of streaming a unique file per user.

FormatUse it forTrade-off
MP4Short downloads and simple demosSlow start, no adaptive bitrate, range-request dependency
HLSVOD and live streamingManifest plus segments; player support varies
DASHAndroid and desktop ecosystemsAnother packaging path and player stack
CMAFLow-latency HLS/DASHMore setup and fewer platform guarantees

For VOD, 4–6 second segments are a good default. Shorter segments improve latency but increase request overhead. For low-latency live, use a different design; don’t copy a VOD ladder into a live event and hope.

A bitrate ladder that doesn’t waste money

Don’t create twelve renditions because a guide says so. Start with four or five that cover real devices, then use quality-defined variable bitrate (QVBR) or per-title analysis where your pipeline supports it.

RenditionResolutionTarget bitrate
360p640 × 360700–900 kbps
480p854 × 4801.2–1.5 Mbps
720p1280 × 7202.5–3 Mbps
1080p1920 × 10804.5–5.5 Mbps
Illustrative starting points, not fixed rules

Audio at 96–128 kbps AAC is usually enough for speech. Captions are not optional if you care about accessibility, search, and corporate buyers. Animation and film grain need more bits than an interview.

Note

The ladder is a hypothesis

Measure your own content. A 1080p talking-head video and a 1080p action sequence should not have the same bitrate budget.

Keep the bucket private

The source bucket should not be public. CloudFront should read it through Origin Access Control, and direct S3 URLs should be blocked. If a video URL works without a signature, assume it will end up in a WhatsApp group.

  • Block public access at the account and bucket level.
  • Use OAC, not a public bucket policy or a legacy origin access identity.
  • Allow TLS only.
  • Sign URLs or cookies with short expiry.
  • Rotate CloudFront key pairs and store the private key on the server.
  • Add WAF rules and rate limits for abuse-prone endpoints.
  • Separate development, staging, and production buckets.

Authorisation belongs in your backend

The player shouldn’t decide who paid. Your API checks the subscription or purchase, then returns a short-lived signed URL or sets a signed cookie. Keep the CloudFront private key on the server.

For HLS, a signed cookie is often more practical than signing every segment URL, because the player requests a manifest and then dozens of parts. A wildcard signed URL policy can work too. Either way, the expiry should be shorter than a typical viewing session and the policy should cover only the content the viewer is entitled to.

playback.tsts
// Server-side only. Never ship the CloudFront private key to the browser.
export async function getPlaybackUrl(userId: string, videoId: string) {
  const entitled = await hasActiveAccess(userId, videoId);
  if (!entitled) throw new Error("Not entitled");

  return signCloudFrontUrl({
    resource: `https://cdn.example.com/videos/${videoId}/*`,
    expires: Date.now() + 2 * 60 * 60 * 1000,
  });
}

The cost that surprises people

Egress usually dominates. A simple estimate: hours viewed × average bitrate ÷ 8 = gigabytes delivered. 1,000 hours at 2 Mbps is about 900 GB, before protocol overhead. Transcoding is spiky; delivery grows with success.

Cost driverLever
DeliveryRight-sized ladder, cache hit ratio, regional edge, shorter content
StorageLifecycle old masters, delete intermediates, tier colder objects
TranscodingQVBR, avoid unnecessary 4K, batch jobs
RequestsSegment length, cache keys, ignore irrelevant query strings
SupportAlarms, retries, dashboards, a cost owner

Put a CloudFront usage alarm and an AWS Budget alert on before launch. The first viral video shouldn’t be the first time you look at the bill.

Practical tip

Make cost a product metric

Track delivery GB per paying user and per active hour. If the number drifts, the ladder, cache, or content length changed.

Monitor the pipeline, not just the player

  • MediaConvert job events through EventBridge, with retries and a dead-letter path.
  • Duration and rendition checks after every transcode.
  • CloudFront 4xx/5xx rates and cache hit ratio.
  • Time to first frame and playback start failures by device.
  • Upload failures and abandoned multipart uploads.
  • Cost anomalies by distribution and content type.

Operations checklist

  1. Block public access and verify with an unauthenticated request.
  2. Confirm CloudFront can read the origin only through OAC.
  3. Set lifecycle rules for masters, intermediates, and old outputs.
  4. Add retries and alarms around MediaConvert jobs.
  5. Test signed access with an expired URL.
  6. Test playback on iOS Safari, Android Chrome, and a slow connection.
  7. Add captions and test them on both players.
  8. Set budget and usage alarms.
  9. Document the reprocessing runbook.
  10. Run a load test against the CDN, not the origin.

Where teams get it wrong

  • A public S3 bucket “just for now”.
  • Streaming MP4 files from the application server.
  • CloudFront keys or AWS credentials in client-side JavaScript.
  • No lifecycle policy, so storage grows forever.
  • Transcoding the same video on every request.
  • One 4K rendition for a catalogue that is mostly watched on phones.
  • No retry or alert when a transcode fails.
  • No cost alarm until the invoice arrives.
  • Ignoring captions and accessibility.

None of this is glamorous. That’s the point. A good streaming platform is measured by how rarely anyone has to think about it.

Keep it boring

Start with the five-piece pipeline, keep the origin private, make access short-lived, and instrument the parts that cost money. You can add DRM, low-latency live, or multi-region later. You can’t easily undo a public bucket or a year of unbudgeted egress.

Direct answers

Questions people actually ask

Short, checkable answers. Every entry here is also published as structured FAQ data for search and answer engines.

Can I use S3 presigned URLs directly instead of CloudFront?

For low-volume internal video, yes. For a subscriber product, CloudFront is usually worth it because it caches segments at the edge, reduces origin load, and gives you central access control. Direct S3 URLs also tend to be long and awkward to manage in a player.

Is a signed CloudFront URL the same as DRM?

No. Signed URLs control who can request a file for a period of time. DRM adds encryption and license management that can survive a determined user capturing the stream. If your content licensing requires DRM, plan for it separately.

How long does this architecture take to build?

A basic VOD pipeline with upload, transcode, CDN, signed playback, and monitoring can take a few weeks for an experienced team. The longer work is usually the admin experience, retries, analytics, and migration of existing content.

Do I need multi-region?

Usually not at the start. CloudFront already delivers from edge locations. Multi-region origin adds complexity and cost. Add it when you have a specific availability or latency requirement that a single well-architected region cannot meet.

References

Sources and further reading

Compliance notes are operational guidance, not legal or tax advice. Rules and thresholds change — confirm your position with a qualified professional.

ZX

Written by

Zynitex Engineering

We design and build the systems behind Zynibill, Invoice Studio, and client platforms like Regalia, Kristive, and ElyteSpark. These notes are the things we wish we had read before shipping them.

More about Zynitex