Build Service
Thesis
Serverless runtime for Next.js apps on AWS Lambda. One Lambda function handles both static file serving and SSR for deployed Next.js apps, pulling deployment bundles from S3 keyed by JOB_ID. Pinned on Zaid's GitHub — the engineering artifact that outlived neploy, the product it was built for.
Status
shipped (pinned, live). Created 2025-05-28. Single-push repo — implementation stable enough that no churn has been needed.
Architecture highlights
- Bundle lifecycle: download bundle from S3 → extract to
/tmp/{JOB_ID}/extractedwithadm-zip→ cache the initialized server in aMapwith 5-minute TTL keyed byJOB_ID→ subsequent requests skip re-init. - Next.js env config on Lambda:
NODE_ENV=production,NEXT_TELEMETRY_DISABLED=1,NEXT_RUNTIME=nodejs,NEXT_SHARP_PATH=<extracted>/node_modules/sharp,NEXT_DIST_DIR=<extracted>/.next,NEXT_BUILD_ID=standalone. - Request shim: Lambda events don't look like Node HTTP requests. The service hand-rolls a Node-compatible request object with: event emitter (
on/once/emit), stream interface (read/pipe), socket simulation (encrypted: true,remoteAddress), cookies, query params, headers. - Response collection: monkey-patches
writeandendon the response to accumulate chunks in a Buffer;finish/closehandlers resolve the promise with a Lambda-format response (statusCode,headers,body). - Timeout fallback: if the response times out but chunks have been collected, return a partial 200 with the collected body.
- Static file detection: path prefix check for
/_next/,/public/,/static/; comprehensive MIME table covering images, fonts, documents, text, archives, media. - Image optimization:
/_next/imagerequests get intercepted — Sharp resizes based onwquery param and re-encodes to JPEG at the givenqquality. Graceful fallback to original image on processing error.
Key decisions
- Server caching with TTL inside the Lambda container: warm containers reuse the initialized Next.js server; reduces cold-start cost when a bundle gets repeated traffic.
- Shimming Node HTTP in userland: Next.js expects standard Node req/res; rather than patching Next, the shim makes Lambda events look like the HTTP server Next expects. Maintainable against Next.js upgrades.
- Partial response on timeout: users get something instead of nothing. Important for Lambda's hard timeout ceilings.
Learnings
- The shim surface (event emitter + streams + socket) is larger than it looks. Even trivial Next.js internals touch
req.socket.encrypted,res.flushHeaders, orreq.on('close', ...). Incomplete shims fail in non-obvious places. - Caching the initialized server per
JOB_IDinside the Lambda instance is the single biggest performance win — cold-extract the bundle once, serve many requests.
Outcomes
- Powered neploy's Next.js deploys. Product archived; engine retained.
- Pinned on profile — Zaid considers this a showcase artifact independent of Neploy's fate.
Open questions
- Is build-service used by anything currently, or is it idle showcase code?
- Does it still work against current Next.js versions (App Router, React Server Components, streaming)?
- Any plan to package it as a standalone OSS tool?
Links
- Source summaries: github-build-service-source
- Parent product: neploy
- Shared patterns: compress-mechanical-labor