When serverless timeout limits block slow work
Every serverless platform caps how long a function can run. Those limits are sensible for HTTP handlers but painful for slow background work: large file processing, bulk API sync, multi-model inference pipelines. The escape hatch is not a longer timeout—it is separating HTTP acceptance from async execution, then chaining pipeline steps that each fit within a step's budget.
Last updated: 2026-06-28
Answer first
Direct answer
When serverless timeout limits block slow work. Inquir separates HTTP acceptance from async execution. The HTTP handler validates input, enqueues a durable background job, and returns 202 immediately—it completes well within any platform timeout. The job then runs outside the HTTP window with its own timeout budget (up to 15 minutes per step), and the queue retries failed steps with backoff.
When it fits
- Work that consistently takes longer than your HTTP platform timeout
- You are hitting Vercel's 60s, Lambda's 900s, or Workers' 30s CPU limit on background jobs that snuck into HTTP handlers
Tradeoffs
- Raising the timeout is a temporary fix, not an architectural one. The work still runs inside a single execution context with one failure domain—a crash at minute 14 of a 15-minute Lambda restarts the whole 15 minutes.
- Recursive invocations (calling yourself to "continue" work) lose context across calls, risk double-writing on failure, and are invisible to any observability tool that expects a single execution trace per job.
Workload and what breaks
Real timeout limits across common serverless platforms
- Vercel Serverless Functions: 60s (Pro), 300s (Enterprise)
- AWS Lambda: 900s (15 min) maximum
- Cloudflare Workers: 30s CPU time (Bundled plan)
- Supabase Edge Functions: 60s
These limits exist for good reasons—serverless functions are designed for fast, stateless HTTP handlers. The problem is when teams try to run background work through the same function execution path: CSV processing, bulk record sync, multi-step ML pipelines, or nightly data archival.
Trade-offs
Why workarounds fall apart
Raising the timeout is a temporary fix, not an architectural one. The work still runs inside a single execution context with one failure domain—a crash at minute 14 of a 15-minute Lambda restarts the whole 15 minutes.
Recursive invocations (calling yourself to "continue" work) lose context across calls, risk double-writing on failure, and are invisible to any observability tool that expects a single execution trace per job.
How Inquir helps
Pipeline chaining as the escape hatch from platform timeout limits
Inquir separates HTTP acceptance from async execution. The HTTP handler validates input, enqueues a durable background job, and returns 202 immediately—it completes well within any platform timeout. The job then runs outside the HTTP window with its own timeout budget (up to 15 minutes per step), and the queue retries failed steps with backoff.
For work longer than 15 minutes per step, decompose into multiple steps—each step fits within the budget, and the pipeline sequences them. See the multi-step pipeline architecture page for fan-out, merge, and per-step retry patterns.
Compare
Serverless platform timeout comparison
HTTP function limits for common platforms, and how Inquir pipeline steps compare.
| Platform | HTTP function limit | Background / async path |
|---|---|---|
| Vercel | 60s (Pro) / 300s (Enterprise) | No built-in background execution |
| AWS Lambda | 900s (15 min) max | Async invoke still caps at 900s |
| Cloudflare Workers | 30s CPU time (Bundled) | 60s with paid Unbound plan |
| Supabase Edge Functions | 60s | No built-in pipeline execution |
| Inquir (HTTP handler) | 5s default / 900s max | — |
| Inquir (pipeline step) | — | Up to 15 min per step; chain steps for longer work |
What you get
What pipeline-backed execution enables
Work that outlasts HTTP timeout limits
HTTP handler returns 202 in milliseconds. Pipeline step runs the slow work with its own timeout—no shared execution context with the HTTP path.
Per-step failure isolation
A failure in step 3 of 5 does not restart steps 1 and 2. Only the failed step retries, with its own retry count and backoff policy.
Status polling and callbacks
Return a jobId from the 202 response. Client polls a status endpoint or receives a webhook callback when the pipeline completes.
Multi-step composition for very long work
Chain steps to exceed the per-step limit: each step runs up to 15 minutes. A 4-step pipeline can cover an hour of work with checkpoints between steps.
What to do next
Pattern: HTTP accepts, pipeline runs
HTTP handler validates and triggers
Parse input, validate, enqueue a durable background job, return 202 with a jobId. This completes in well under any HTTP platform timeout.
Pipeline step does the slow work
The step runs outside the HTTP window with its own timeout budget (up to 15 min). Chain steps for work that exceeds a single step budget.
Client polls or receives callback
Use the jobId to poll a status endpoint, or have the final pipeline step POST a webhook to the client when complete.
Code example
HTTP → pipeline handoff: escape the timeout
The HTTP handler returns 202 immediately—it never approaches the platform timeout. The pipeline step runs the slow work outside the HTTP window.
export async function handler(event) { const { fileUrl } = JSON.parse(event.body || '{}'); if (!fileUrl) return { statusCode: 400, body: JSON.stringify({ error: 'fileUrl required' }) }; // Returns in <100ms — well inside Vercel 60s, Lambda 900s, or any other platform limit const { jobId } = await global.jobs.enqueue('import-csv', { fileUrl }); return { statusCode: 202, body: JSON.stringify({ jobId, status: 'started' }) }; }
export async function handler(event) { // Runs outside HTTP window; this step has up to 15 min timeout const { fileUrl } = event.payload ?? {}; const rows = await downloadAndParseCSV(fileUrl); // may take several minutes for large files for (const batch of chunk(rows, 500)) { await db.upsertBatch(batch); // idempotent by row ID } return { imported: rows.length, fileUrl }; }
When it fits
When the HTTP→pipeline pattern applies
When this works
- Work that consistently takes longer than your HTTP platform timeout
- You are hitting Vercel's 60s, Lambda's 900s, or Workers' 30s CPU limit on background jobs that snuck into HTTP handlers
When to skip it
- Work that completes in under 10 seconds—keep it synchronous in the HTTP handler for simpler debugging
FAQ
FAQ
Is a pipeline step truly unlimited in time?
No. Each pipeline step has a configurable timeout, up to 15 minutes (900,000ms). This is much longer than any HTTP function timeout, but it is not unlimited. For work longer than 15 minutes, chain multiple steps—see the long-running serverless jobs page for multi-step decomposition.
How does this differ from raising the Lambda timeout to 900s?
Lambda caps the entire execution at 900s in one execution context. Inquir chains steps, each with its own 15-minute budget and independent retry. A crash at minute 14 of one step does not restart a prior step that already completed.
What if the client needs a synchronous result?
For synchronous results, the client must poll a status endpoint using the jobId, or you configure the final pipeline step to POST a callback to the client. True synchronous long-running work is fundamentally incompatible with serverless HTTP timeouts on any platform.