Inngest step return 4 MiB limit: return the Sume artifact URL

Inngest caps one step return at 4 MiB and run state at 32 MiB. Return the media.sume.com artifact URL from step.run instead of the video bytes.

4 min readSume
All posts

A step in an Inngest function can return at most 4 MiB, so never return a rendered video from step.run. Return the Sume artifact URL, a string of a few hundred bytes, and let the next step or the consumer fetch the file from media.sume.com when needed.

Limits are from the Inngest usage limits page, and job behavior from Sume's Core workflow and Jobs and results, read 2026-09-30.

What are the Inngest limits?

The page lists the step return cap and the run state cap, and gives the same advice for both: keep large data outside Inngest state.

Inngest limits relevant to media jobs, from the Inngest usage limits page read 2026-09-30.
LimitValueGuidance on the page
Step return4 MiB returned by one stepStore large results outside step state and return a reference
Function run state32 MiB across event data, step data, return data, metadataKeep large data outside run state
Event size256 KiB to 3 MiB depending on planNot stated on the page; keep payloads small and pass references

What does a completed Sume job give me?

A completed job carries result.artifacts[] entries with id, url, type and content_type. The docs say Sume-owned artifact URLs under https://media.sume.com are the public contract, and that integrations should store the Sume URL rather than raw provider URLs. That URL is the reference Inngest asks you to return.

How do I avoid polling inside steps?

Submit with mode: "webhook" and wait for the event. Sume sends terminal job events only, and results are available only after completion, so a step should not fetch the result before the event arrives. The pattern is covered in Inngest: wait for an AI video webhook.

// inside an Inngest function
const url = await step.run("get-artifact-url", async () => {
  const res = await fetch("https://api.sume.com/v1/jobs/" + jobId + "/result", {
    headers: { Authorization: "Bearer " + process.env.SUME_API_KEY },
  });
  const body = await res.json();
  const job = body.data ?? body; // the OpenAPI schema wraps the payload in data
  return job.result.artifacts[0].url; // a string, not the video
});

What should the next step do with the URL?

Pass the URL to whatever needs the file: a publish call, a Timeline input, a CMS field. If a step genuinely must read the bytes, stream them to your own storage inside that step and return only the new reference, so neither the step return nor the 32 MiB run state grows with video size.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume