Skip to main content
Back to Blog

Serverless EngineeringJun 23, 20265 min read

Serverless File Conversion API: AWS Lambda Without ffmpeg

Hasnain NisarAutomation engineer · Nisar Automates
Serverless File Conversion API: AWS Lambda Without ffmpeg

Serverless File Conversion API: AWS Lambda Without ffmpeg

TL;DR: - AWS Lambda's 250 MB deployment package limit makes bundling ffmpeg, LibreOffice, or similar native binaries painful and fragile - A serverless file conversion API moves conversion work out of Lambda, letting you handle S3 events and webhooks with thin, fast functions - Convertfleet's HTTP API converts documents, images, videos, and audio with a single POST request—no layers, no cold-start penalty from heavy binaries - This guide shows the exact Lambda function, IAM policy, and event wiring you need

Your Lambda function needs to convert a PDF to JPG, a Word doc to PDF, or trim a video clip. The standard answer—bundle ffmpeg or LibreOffice into a Lambda layer—works until it doesn't. That layer balloons past 250 MB. Deployments fail. Cold starts drag to 8–10 seconds. You split the binary, fetch it from S3 on init, cache in /tmp, and pray the ephemeral storage holds.

There is a cleaner path. Move conversion to a managed API, keep Lambda for orchestration. This article shows how to build an event-driven file processing pipeline that stays inside Lambda's limits while handling real document and media workloads.


What breaks when you bundle ffmpeg into Lambda?

The 250 MB deployment package limit is a hard ceiling, not a suggestion. AWS Lambda allows up to 50 MB zipped (or 250 MB unzipped) for direct uploads. A minimal ffmpeg build runs 120–150 MB. Add LibreOffice for document conversion and you are underwater before your own code ships.

Teams work around this with:

  • Lambda layers: split the binary, but layers count toward the same limit
  • Container images: up to 10 GB, but cold starts jump to 5–15 seconds and local testing gets complex
  • S3 fetch on init: download ffmpeg to /tmp at runtime, but this adds latency and fails when the 512 MB tmp storage is exhausted

In 2024, AWS raised the container image limit to 10 GB, but the deployment package limit stayed fixed. For high-throughput, low-latency conversion, these workarounds trade one problem for another.


How does a serverless file conversion API solve this?

A serverless file conversion API moves the heavy binary and processing to a managed service, leaving Lambda to do what it does best: route events, validate inputs, and manage state.

The pattern is simple:

  1. File lands in S3 (or arrives via webhook)
  2. Lambda receives the event, validates it, generates a presigned URL
  3. Lambda POSTs the file (or its URL) to the conversion API
  4. API processes, returns the converted file to S3 or a callback URL
  5. Lambda logs, notifies, or triggers next steps

Lambda's role shrinks to a thin orchestrator. No ffmpeg. No LibreOffice. No layer management.


Serverless ffmpeg alternative: comparing the approaches

Approach Size Cold start Maintenance Best for
Native Lambda layer (ffmpeg) 150–250 MB 3–5 s High Air-gapped environments
Container image with ffmpeg 500 MB–2 GB 5–15 s Medium Complex multi-step pipelines
External conversion API < 5 MB < 1 s Low Most production workloads
Lambda + ECS Fargate task Variable 30–60 s High Batch conversion at massive scale

The external API wins on every dimension except total isolation. If your compliance regime requires all processing inside your AWS account, the layer or container stays necessary. For everyone else, the operational savings are substantial.


Building the ad Lambda function: step-by-step

This section walks through a complete, deployable setup. You will need an AWS account, the AWS CLI configured, and a Convertfleet API key.

Prerequisites

  • AWS CLI v2 installed and configured
  • IAM role with Lambda execution permissions and S3 read/write
  • Convertfleet account with API key (free tier available)

Step 1: Create the IAM role

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": "arn:aws:s3:::your-bucket/*"
    }
  ]
}

Attach this to a role named lambda-convert-role.

Step 2: Write the Lambda function

Create index.js:

const https = require('https');
const { S3Client, GetObjectCommand, PutObjectCommand } = require('@aws-sdk/client-s3');
const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

const s3 = new S3Client({ region: process.env.AWS_REGION });
const CONVERTFLEET_KEY = process.env.CONVERTFLEET_API_KEY;

exports.handler = async (event) => {
  // Triggered by S3 put event or API Gateway
  const bucket = event.Records[0].s3.bucket.name;
  const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '));

  // Generate presigned URL for source file
  const getCommand = new GetObjectCommand({ Bucket: bucket, Key: key });
  const sourceUrl = await getSignedUrl(s3, getCommand, { expiresIn: 300 });

  // Request conversion via Convertfleet API
  const conversion = await fetch('https://api.convertfleet.com/v1/convert', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${CONVERTFLEET_KEY}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      source_url: sourceUrl,
      target_format: 'pdf', // or jpg, mp4, etc.
      webhook_url: `https://your-api.com/webhook/convert-complete`
    })
  });

  const result = await conversion.json();
  console.log('Conversion job started:', result.job_id);

  return { statusCode: 202, body: JSON.stringify({ jobId: result.job_id }) };
};

Key detail: The function never touches the file contents directly. It passes a presigned URL to the conversion service, keeping memory usage minimal.

Step 3: Package and deploy

# Initialize project
mkdir lambda-convert && cd lambda-convert
npm init -y
npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

# Zip deployment package (under 5 MB with dependencies)
zip -r function.zip index.js node_modules

# Create function
aws lambda create-function \
  --function-name file-converter \
  --runtime nodejs20.x \
  --handler index.handler \
  --role arn:aws:iam::YOUR_ACCOUNT:role/lambda-convert-role \
  --zip-file fileb://function.zip \
  --environment Variables="{CONVERTFLEET_API_KEY=your_key_here}" \
  --memory-size 512 \
  --timeout 30

Step 4: Wire S3 event trigger

aws s3api put-bucket-notification-configuration \
  --bucket your-bucket \
  --notification-configuration '{
    "LambdaFunctionConfigurations": [{
      "LambdaFunctionArn": "arn:aws:lambda:us-east-1:YOUR_ACCOUNT:function:file-converter",
      "Events": ["s3:ObjectCreated:*"],
      "Filter": {
        "KeyFilterRules": [{
          "Name": "prefix",
          "Value": "uploads/"
        }]
      }
    }]
  }'

Test it: Upload a .docx to s3://your-bucket/uploads/. The Lambda fires, Convertfleet converts, and your webhook receives the completed file URL.


Common mistakes and how to avoid them

Mistake 1: Passing file contents in the Lambda payload

Lambda has a 6 MB synchronous invocation payload limit. For larger files, always use presigned S3 URLs and stream. Passing base64-encoded video through API Gateway is a recipe for 413 errors.

Mistake 2: Ignoring the conversion webhook

Do not poll for completion. The Convertfleet API sends a webhook when conversion finishes. Set up an API Gateway endpoint or a second Lambda (via Function URL) to receive it. Polling burns Lambda invocations and complicates your state machine.

Mistake 3: Hardcoding output paths

Use the original S3 key with a transformed suffix (input.docxinput.pdf) rather than a flat output folder. This prevents collisions and makes cleanup logic trivial.

Mistake 4: Forgetting IAM for presigned URLs

The presigned URL generation requires s3:GetObject on the source and s3:PutObject on the destination. A common slip is granting read but not write, causing the conversion service to fail silently.


Why event-driven file processing beats synchronous conversion

Synchronous conversion—where the client waits for the result—caps your throughput at API Gateway's 29-second timeout. Event-driven architecture removes this ceiling.

With the pattern above:

  • Uploads are instant; users get a job ID immediately
  • Conversion happens asynchronously; large video files take minutes without blocking
  • Webhooks notify downstream systems; no polling loops
  • Failed jobs retry via SQS or Step Functions if you add them

This is how Netflix processes uploads, how YouTube handles transcoding, and how any team processing more than a few files per minute should architect. The file content conversion formats and methods guide covers format-specific considerations in more depth.


What are the advantages of fleet conversion?

The term "fleet conversion" spans two distinct domains—vehicle fleets and file processing pipelines. Both share a core logic: transforming existing assets for new operational requirements.

For vehicle fleets: Electric fleet conversion replaces combustion engines with electric drivetrains, reducing total cost of ownership by 40–60% over vehicle lifetime according to 2024 DOE fleet analysis. Benefits include lower fuel costs, reduced maintenance (fewer moving parts), compliance with emissions regulations, and alignment with corporate sustainability targets. Private fleet conversions often qualify for federal tax credits under the Inflation Reduction Act.

For file processing fleets: The advantages mirror the vehicle analogy. Converting from self-managed binary layers to a managed serverless file conversion API reduces operational overhead, eliminates version maintenance, and scales without provisioning. The "fleet" of conversion workers becomes elastic—ramping from zero to thousands of concurrent jobs without capacity planning.

The decision framework is identical: when does the cost of maintaining legacy infrastructure exceed the cost of modernizing? For most teams processing documents or media at scale, that tipping point arrives quickly.


When should you still run ffmpeg in Lambda?

A managed API is not universal. Keep native binaries when:

  • Compliance requires data residency that third-party APIs cannot guarantee
  • Network egress is restricted (air-gapped or classified environments)
  • Conversion logic is custom (proprietary codecs, watermarking, or manipulation that generic APIs do not support)
  • Cost at extreme scale makes per-request API pricing uneconomical versus amortized EC2

For these cases, the container image approach with AWS Fargate or a dedicated EC2 instance remains appropriate. The free file conversion software tested in 2026 covers self-hosted options for comparison.


Wiring webhooks and monitoring

Production systems need observability. Add these to your stack:

Component Purpose AWS Service
Dead letter queue Capture failed conversions for retry SQS
Conversion metrics Track duration, success rate, format distribution CloudWatch
Alerting Notify on error thresholds SNS → Email/Slack
Audit log Retain conversion records for compliance DynamoDB

Webhook verification: Always verify the webhook signature. Convertfleet signs payloads with your account secret. A minimal verification in your handler:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret) {
  const hmac = crypto.createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(signature));
}

Frequently Observatory and statistics

Real-world data shapes architecture decisions. Consider these figures:

Metric Value Source
Lambda deployment package limit 250 MB unzipped AWS documentation, 2024
Lambda container image limit 10 GB AWS re:Invent 2024 announcement
Typical ffmpeg binary size 120–150 MB Community builds, varies by codec support
LibreOffice headless binary 300–400 MB The Document Foundation releases
Lambda cold start (zip, 512 MB) 150–300 ms CloudWatch measurements, Node.js 20.x
Lambda cold start (container, 2 GB) 5, HUDSON CloudWatch measurements, 2024

A 2023 study by Datadog found that 32% of Lambda functions using container images experienced cold starts exceeding 3 seconds, compared to 8% for zip-deployed functions. For conversion workloads where latency matters, this gap is decisive.


Free download

To make this actionable, we built a free resource you can grab right now — no signup:

Frequently Asked Questions

What is the maximum file size for Lambda-based conversion workflows?

Lambda itself has a 6 MB synchronous payload limit and 10 GB ephemeral storage. With the external API pattern described here, file size limits shift to what the conversion service and S3 support—typically multi-gigabyte files via multipart upload and presigned URLs.

What are the benefits of private fleet conversion for document processing?

Private fleet conversion in this context means maintaining conversion infrastructure within your own AWS account and VPC. Benefits include data never leaving your environment, custom security controls, and predictable flat costs versus per-request pricing. The trade-off is engineering overhead.

How does Convertfleet compare to AWS Elemental MediaConvert for video?

AWS Elemental MediaConvert is purpose-built for broadcast-grade video transcoding with complex encoding profiles. Convertfleet handles general-purpose file conversion—documents, images, audio, and video—through a unified API with simpler integration. Choose MediaConvert for streaming pipelines; use Convertfleet for mixed-format document and media workflows.

Can this pattern work with Step Functions for complex workflows?

Yes. Replace the direct Lambda-S3 trigger with Step Functions when you need branching logic— for example, routing .docx to PDF conversion, .mov to MP4 transcoding, and .zip to extraction, each with different retry policies and downstream consumers.

What is the typical cold start for this Lambda configuration?

With the thin dependencies used here (@aws-sdk/client-s3 optimized for Lambda), cold starts average 150–300 ms at 512 MB memory. This is 10–50× faster than container-based approaches with ffmpeg bundled.


Conclusion

Bundling ffmpeg into Lambda is a solved problem that creates new problems. The 250 MB limit, cold start latency, and maintenance burden push teams toward complexity they do not need. A serverless file conversion API returns Lambda to its strength—fast, event-driven orchestration—while a managed service handles the heavy conversion work.

The function above deploys in minutes, handles S3 and webhook triggers, and stays under 5 MB. For teams building document pipelines, media workflows, or any system that transforms files at scale, this architecture is the pragmatic default.

Start building with Convertfleet — free tier includes 100 conversions per month, no credit card required.

Share

Read next