Ask
84
@orm_tamsin ·

PDF generating server action dies at the same point in production, is maxDuration even respected for actions

Next 15 app router deployed on Vercel. The action renders a PDF and uploads it, which takes 45 to 90 seconds locally depending on the document. In production it fails part way with no useful error, and my attempt to add export const maxDuration to the actions file broke the build. Two of us, and this is the last thing before launch.

8 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @two_vcpu_club · 2d ago

    Worth checking the project level default too, since a lot of people are running with an old value they set once. In the current docs the platform default duration is five minutes on every plan with fluid compute, with a higher ceiling on paid plans, and there is a per function extended duration option in beta that goes considerably further. But your project settings can override that downward, and dashboard settings under Functions is where a forgotten fifteen second default hides. Check what your project says before assuming the platform is the constraint.

    75
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @deadbug_wiring · yesterday · 3 replies

    The build break is the clue. In a file with 'use server' at the top, every export has to be an async function, so exporting a const of any kind fails by design. maxDuration is route segment config, which means it belongs in the page, layout or route handler that the request goes through, not in the module where the action is defined. A server action runs inside the request for the route that invoked it, so it inherits that route's duration, and putting the export on the page that hosts the form is what actually changes anything.

    107
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @orm_tamsin · 23h ago

      That explains both symptoms at once. I had the export sitting in actions.ts and assumed it was being ignored rather than rejected.

      32
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @swatch_sonia · 2d ago

      It is rejected loudly, which is at least honest. Put it on the page and redeploy before you change anything else, so you know what the limit was really doing.

      24
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @internal_linker · 2d ago · 2 replies

    I would not fix the timeout, I would delete the requirement. Ninety seconds of work inside a request means the user is staring at a spinner, any proxy or flaky connection between them and you can kill it, and a retry runs the whole thing again. The shape that has never let me down is: the action writes a job row and returns immediately, a background worker or a queue consumer does the render and the upload, and the client polls or subscribes for the result. It is an afternoon of work and it makes the whole class of problem go away, including the ones you have not hit yet.

    87
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @leaky_bucket_ed · yesterday

      Strongly agree. We limped along on a raised timeout for months and every incident traced back to it eventually.

      28
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @layer_shift_lu · 11h ago

    I raised the duration, it deployed, and I then discovered two new problems that were worse. Users with no visible progress clicked the button again and I got duplicate PDFs, and a proxy in front of us closed the connection well before the function finished anyway, so the work completed on the server and the browser saw a failure. If you do stay synchronous, disable the button through the pending state and stream something back so the connection has traffic on it.

    71
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @yaml_yuri · 10h ago

    Segment config goes on the route, not the actions file. Check the project default in settings. Then move the render off the request path anyway.

    55
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report