Architecture & Limits
5 min readUpdated August 2026

Overcoming HubSpot 20-Second Workflow Execution Timeouts

Explore strategies to bypass HubSpot’s strict 20-second custom code execution timeout using Workflood async queues, batching, and gVisor sandboxes.

The Problem: The 20-Second Hard Limit

HubSpot native custom code actions enforce a strict **20-second execution timeout** and a **128MB memory ceiling**.

If your custom action performs any of the following, it will frequently timeout: - Batch searching 500+ records across multi-tier association trees. - Calling slow third-party enrichment APIs (ZoomInfo, Clearbit, OpenAI). - Calculating historical pipeline velocity over 12 months of deal history. - Performing PDF generation or large file transformations.

When a HubSpot custom code action times out, the workflow halts, leaving records in a broken or unassigned state.

How Workflood Solves Execution Limits

Workflood decouples action execution from HubSpot's synchronous workflow canvas:

  • **Immediate Webhook Acknowledgement:** HubSpot's webhook step receives a `202 Accepted` response in <100ms.
  • **Dedicated Redis / BullMQ Queue:** The action payload is pushed into an isolated, reliable job queue.
  • **gVisor Micro-Containers:** Execution runs with up to **512MB RAM** and extended timeouts:
  • - **Single Portal Plan:** **60-second** execution timeout (3x HubSpot native).
  • - **Multi-Portal / Agency Plan:** Up to **5-minute (300s)** execution timeout (15x HubSpot native).
  • **Asynchronous API Write-Back:** Once computation finishes, Workflood writes the results back to HubSpot using the pre-authenticated SDK.

Timeout Comparison Matrix

FeatureHubSpot Native Data HubWorkflood Single PortalWorkflood Multi-Portal / Agency
**Max Execution Time****20 seconds (Hard Cap)****60 seconds****300 seconds (5 min)**
**Memory Allocation**128 MB512 MB1024 MB+
**Cold Starts**500ms – 2000ms<50msZero cold starts
**Failure Handling**Halts entire workflowAuto-retries with jitter & Slack alertsAuto-retries & dead-letter queue

Code Example: Chunked Batch Processing

For heavy operations involving hundreds of records, use chunked pagination:

chunked-sync.ts
export default async function main() {
  let after: string | undefined = undefined
  let totalProcessed = 0

  do {
    const page = await hubspot.client.crm.contacts.basicApi.getPage(
      100, // Batch size
      after,
      ['email', 'annualrevenue', 'hs_lead_status']
    )

    // Process chunk in parallel
    await Promise.all(
      page.results.map(async (contact) => {
        // Business logic calculation
        totalProcessed++
      })
    )

    after = page.paging?.next?.after
  } while (after && totalProcessed < 2000)

  return { totalProcessed, status: 'completed' }
}

Frequently Asked Questions

Can I set a custom timeout per action in Workflood?

Yes. In the Workflood action editor settings, you can configure the exact timeout in seconds per action up to your workspace plan limit.