Skip to content

perf(website-server): Enable Node.js compile cache for faster cold starts#1066

Merged
yamadashy merged 3 commits intomainfrom
perf/website-server-compile-cache
Jan 3, 2026
Merged

perf(website-server): Enable Node.js compile cache for faster cold starts#1066
yamadashy merged 3 commits intomainfrom
perf/website-server-compile-cache

Conversation

@yamadashy
Copy link
Copy Markdown
Owner

Enable V8 compile cache to reduce Cloud Run cold start latency.

Summary

This PR implements Node.js compile cache (available since v22.8.0) to speed up server startup on Cloud Run cold starts.

How it works

  1. Build time: Run warmup.mjs to import all modules and generate compile cache
  2. Runtime: Use pre-compiled cached code instead of compiling on each cold start

Changes

  • warmup.mjs: New script that imports server module and flushes compile cache to disk
  • src/index.ts: Add WARMUP_MODE check to skip server initialization during warmup
  • Dockerfile: Set NODE_COMPILE_CACHE env var and run warmup script during build

Reference

Note

Since the server is already bundled with esbuild, the improvement may be less dramatic than unbundled setups. However, the implementation cost is minimal and it still helps with:

  • Compilation of the bundled server.mjs file itself
  • External dependencies (tinypool, tiktoken)

Checklist

  • Run npm run test
  • Run npm run lint

yamadashy and others added 2 commits January 3, 2026 16:47
…arts

Add V8 compile cache support to reduce Cloud Run cold start latency.
The cache is pre-generated at Docker build time using a warmup script,
so subsequent container starts use pre-compiled code.

Changes:
- Add warmup.mjs script to generate compile cache at build time
- Add WARMUP_MODE check to skip server initialization during warmup
- Set NODE_COMPILE_CACHE environment variable in Dockerfile
- Run warmup script during Docker build to pre-populate cache
The warmup script was hanging during Docker build because some modules
(like winston/LoggingWinston) keep the event loop alive. Adding an
explicit process.exit(0) ensures the warmup script terminates after
generating the compile cache.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 3, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

This change introduces V8 compile cache optimization to reduce Node.js startup latency. A new warmup script pre-generates compile cache during Docker build by importing dependencies, and server initialization is updated to skip startup during warmup mode.

Changes

Cohort / File(s) Summary
Docker configuration
website/server/Dockerfile
Copy warmup.mjs from builder to runtime image; add NODE_COMPILE_CACHE environment variable pointing to /app/.compile-cache; execute node warmup.mjs during build to pre-generate V8 compile cache.
Server initialization
website/server/src/index.ts
Add isWarmupMode() function to check WARMUP_MODE environment variable; update initialization guard to skip server startup when in warmup mode or running as Tinypool worker.
Warmup script
website/server/warmup.mjs
New script that enables Node compile cache, sets warmup mode flag, dynamically imports bundled server module to trigger dependency compilation, flushes cache to disk, and logs completion.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change—enabling Node.js compile cache for performance improvements.
Description check ✅ Passed The description is comprehensive, covering the motivation, implementation details, and includes references and notes; the checklist is fully completed.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @yamadashy, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a performance optimization aimed at reducing the cold start latency of the website server. By leveraging the Node.js V8 compile cache, the server's modules are pre-compiled during the Docker build process. This ensures that when the server starts in a production environment, particularly on platforms like Cloud Run, it can utilize already compiled code, leading to faster startup times and improved responsiveness.

Highlights

  • Node.js Compile Cache: Enabled the V8 compile cache for the website server to reduce cold start latency, especially beneficial for environments like Cloud Run.
  • Warmup Script Introduction: Added a new "warmup.mjs" script responsible for importing all server modules and flushing the generated compile cache to disk during the build phase.
  • Dockerfile Updates: Modified the Dockerfile to integrate the compile cache generation process, including copying the warmup script, setting the "NODE_COMPILE_CACHE" environment variable, and executing the warmup script.
  • Conditional Server Initialization: Updated "src/index.ts" to introduce a "WARMUP_MODE" check, preventing the full server initialization during the build-time warmup process to ensure only compilation occurs.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively implements the Node.js compile cache to reduce server cold start latency. The approach of using a warmup.mjs script during the Docker build is sound, and the necessary changes in the server's entry point to accommodate a 'warmup mode' are correctly implemented. The code is clear and follows best practices for this feature. I have one suggestion to optimize the final Docker image by removing the warmup script after it's used, which will help in keeping the image size minimal.

@codecov
Copy link
Copy Markdown

codecov bot commented Jan 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.19%. Comparing base (ad9b3e7) to head (78cf278).
⚠️ Report is 4 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1066   +/-   ##
=======================================
  Coverage   87.19%   87.19%           
=======================================
  Files         116      116           
  Lines        4350     4350           
  Branches     1011     1011           
=======================================
  Hits         3793     3793           
  Misses        557      557           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Jan 3, 2026

Deploying repomix with  Cloudflare Pages  Cloudflare Pages

Latest commit: 78cf278
Status: ✅  Deploy successful!
Preview URL: https://10509484.repomix.pages.dev
Branch Preview URL: https://perf-website-server-compile.repomix.pages.dev

View logs

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Jan 3, 2026

PR Review: perf(website-server): Enable Node.js compile cache for faster cold starts

Overview

This PR enables V8 compile cache (Node.js v22.8.0+) to reduce Cloud Run cold start latency by pre-compiling modules during Docker build time.

✅ Strengths

  1. Clean implementation - The changes are minimal and well-organized across three files
  2. Good documentation - Clear comments explain the purpose of each change
  3. Proper feature detection - Uses NODE_COMPILE_CACHE env var as documented by Node.js
  4. Non-invasive - The warmup mode check integrates cleanly with existing tinypool worker check
  5. Version compatibility - Dockerfile uses Node 24 which supports these APIs

📋 Code Quality Assessment

Details

warmup.mjs

  • Good use of JSDoc-style documentation with reference link
  • Properly calls flushCompileCache() to ensure cache is written before container build completes
  • Sets WARMUP_MODE before import to prevent side effects

src/index.ts

  • Clean extraction of isWarmupMode() helper function
  • Follows existing pattern of isTinypoolWorker()
  • Logical OR condition is correct: skip initialization for either workers or warmup

Dockerfile

  • Correct placement of warmup after ENV declarations
  • Good comments explaining the purpose
  • Warmup script is properly copied before being executed

⚠️ Minor Considerations

Details
  1. Error handling in warmup.mjs: The script doesn't have try/catch around the import. If the import fails, the Docker build will fail (which is actually the desired behavior - fail fast during build).

  2. Cache directory permissions: The /app/.compile-cache directory will be created by Node.js automatically. In Alpine containers this typically works fine, but worth monitoring.

  3. No benchmarks included: The PR description honestly notes the improvement "may be less dramatic" due to esbuild bundling. It would be nice to have before/after cold start measurements, but not blocking.

🔍 Potential Failure Scenarios (Premortem)

Details
Scenario Risk Mitigation
Node.js version mismatch between build and runtime Low Both stages use same base image (node:24-alpine)
Compile cache corruption Low Cache is regenerated on each Docker build
Memory overhead from cache Low Compile cache is typically small; worth monitoring
API changes in future Node versions Low Using stable documented APIs
Warmup import failure Medium Build would fail immediately - add try/catch with clear error message if you want more graceful handling

🛡️ Security Review

No security concerns. The changes don't affect:

  • Input validation
  • Authentication/authorization
  • External API interactions
  • File system access patterns

📊 Test Coverage

The website server doesn't have unit tests (no test files found in website/server/). The compile cache feature is tested implicitly by the Docker build succeeding. For a performance optimization like this, integration testing via successful deployment is appropriate.

Verdict

LGTM ✅ - This is a well-implemented, low-risk performance optimization with minimal code changes. The implementation follows Node.js best practices and integrates cleanly with the existing codebase.


Reviewed by Claude

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
website/server/warmup.mjs (1)

11-25: Consider adding error handling for robustness.

The warmup script lacks error handling. While Docker build failures will surface if the script exits with non-zero status, explicit try-catch blocks would provide clearer error messages during build-time debugging.

🔎 Proposed error handling
+try {
   // Enable compile cache (uses NODE_COMPILE_CACHE env var for directory)
   enableCompileCache();
 
   // Set warmup mode to prevent server from actually starting
   process.env.WARMUP_MODE = 'true';
 
   // Import the server module to trigger compilation of all dependencies
   await import('./dist-bundled/server.mjs');
 
   // Flush cache to disk immediately (default is on process exit)
   flushCompileCache();
 
   console.log('Compile cache generated successfully');
+} catch (error) {
+  console.error('Failed to generate compile cache:', error);
+  process.exit(1);
+}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ad9b3e7 and 0ca186e.

📒 Files selected for processing (3)
  • website/server/Dockerfile
  • website/server/src/index.ts
  • website/server/warmup.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
  • GitHub Check: Test (windows-latest, 24.x)
  • GitHub Check: Test (macos-latest, 25.x)
  • GitHub Check: Build and run (windows-latest, 24.x)
  • GitHub Check: Test (macos-latest, 24.x)
  • GitHub Check: Test (ubuntu-latest, 25.x)
  • GitHub Check: Build and run (windows-latest, 25.x)
  • GitHub Check: Test (windows-latest, 20.x)
  • GitHub Check: Test (windows-latest, 22.x)
  • GitHub Check: Build and run (windows-latest, 20.x)
  • GitHub Check: Build and run (windows-latest, 22.x)
  • GitHub Check: Test with Bun (windows-latest, latest)
  • GitHub Check: claude-review
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
website/server/src/index.ts (2)

25-28: LGTM! Clean warmup mode implementation.

The isWarmupMode() function correctly checks the environment variable to determine if running in warmup mode. This aligns well with the existing isTinypoolWorker() pattern.


30-31: Server initialization guard correctly updated.

The condition now properly skips server initialization in both Tinypool worker mode and warmup mode, which is essential for compile cache generation during Docker build.

website/server/Dockerfile (3)

47-48: Warmup script correctly copied from builder stage.

The warmup script is properly copied from the builder stage to the runtime image, enabling compile cache generation during Docker build.


50-56: Environment variables properly configured for compile cache.

The NODE_COMPILE_CACHE=/app/.compile-cache environment variable correctly specifies the cache directory. The warmup script will use this location to store pre-compiled bytecode.


58-60: Compile cache generation correctly integrated into build process.

Running node warmup.mjs during the Docker build ensures the compile cache is pre-generated before the runtime container starts. The implementation is sound:

  • NODE_COMPILE_CACHE environment variable is properly set to /app/.compile-cache before the warmup script executes
  • warmup.mjs uses the official Node.js enableCompileCache() API from the node:module module
  • The server respects the WARMUP_MODE flag and skips initialization during cache generation
  • flushCompileCache() ensures the cache is persisted to disk before the build completes
  • Node.js 24 (specified in Dockerfile) fully supports this feature

This will reduce cold start latency by pre-compiling all modules at build time rather than on first run.

website/server/warmup.mjs (1)

11-14: No compatibility issues detected—Node.js 24 in the base image fully supports the compile cache API.

The node:24-alpine image in website/server/Dockerfile meets the requirement. Node.js 24.x is well above the minimum v22.8.0 where compile cache APIs were introduced.

@claude
Copy link
Copy Markdown
Contributor

claude bot commented Jan 3, 2026

PR Review: perf(website-server): Enable Node.js compile cache for faster cold starts

Summary

This PR implements Node.js V8 compile cache (available since v22.8.0) to reduce Cloud Run cold start latency by pre-compiling modules during Docker build time.

✅ Overall Assessment: LGTM

This is a well-implemented, low-risk performance optimization with minimal code changes. The implementation follows Node.js best practices and integrates cleanly with the existing codebase.


Strengths

  1. Clean implementation - The changes are minimal and well-organized across three files
  2. Good documentation - Clear comments explain the purpose of each change, with reference to Node.js docs
  3. Proper feature detection - Uses NODE_COMPILE_CACHE env var as documented by Node.js
  4. Non-invasive - The warmup mode check integrates cleanly with existing isTinypoolWorker() pattern
  5. Version compatibility - Dockerfile uses Node 24 which fully supports these APIs
  6. Honest assessment - PR description acknowledges that gains may be less dramatic due to esbuild bundling

Code Quality Assessment

Details

warmup.mjs

  • Good use of JSDoc-style documentation with reference link
  • Properly calls flushCompileCache() to ensure cache is written before container build completes
  • Sets WARMUP_MODE before import to prevent side effects
  • Explicit process.exit(0) addresses the winston/logging event loop issue documented in commit message

src/index.ts

  • Clean extraction of isWarmupMode() helper function
  • Follows existing pattern of isTinypoolWorker()
  • Logical OR condition is correct: skip initialization for either workers or warmup

Dockerfile

  • Correct placement of warmup after ENV declarations
  • Good comments explaining the purpose
  • Warmup script is properly copied before being executed

🔍 Potential Failure Scenarios (Premortem)

Details
Scenario Risk Mitigation
Node.js version mismatch between build and runtime Low Both stages use same base image (node:24-alpine)
Compile cache corruption Low Cache is regenerated on each Docker build
Memory overhead from cache Low Compile cache is typically small; worth monitoring
API changes in future Node versions Low Using stable documented APIs
Warmup import failure Low Build would fail immediately, providing fast feedback

🛡️ Security Review

No security concerns identified:

  • No changes to input validation
  • No changes to authentication/authorization
  • No external API interaction changes
  • No file system access pattern changes

📊 Test Coverage

Per Codecov: All modified and coverable lines are covered. Project coverage remains at 87.19%. For a performance optimization like this, the Docker build success serves as effective integration testing.


💡 Optional Suggestions (Non-blocking)

Details
  1. Error handling in warmup.mjs: Consider adding try/catch for clearer error messages during Docker build debugging:

    try {
      enableCompileCache();
      // ... rest of script
    } catch (error) {
      console.error('Failed to generate compile cache:', error);
      process.exit(1);
    }
  2. Remove warmup script after use (as Gemini suggested): Could reduce image size slightly by adding && rm warmup.mjs to the RUN command. However, the file is small (~600 bytes) and keeping it aids debugging, so this is truly optional.

  3. Consider adding cold start benchmarks: Before/after measurements would quantify the improvement, though not required for merge.


Verdict

Approved ✅ - Clean, well-documented performance optimization with minimal risk.


Reviewed by Claude

Add compile cache directory to server startup metrics log to help
verify that the Node.js compile cache is properly enabled in production.
@claude
Copy link
Copy Markdown
Contributor

claude bot commented Jan 3, 2026

Follow-up PR Review

I've re-reviewed this PR. Since my previous reviews (visible above), the only additional commit adds compile cache directory logging on startup (module.getCompileCacheDir()), which is a valuable observability improvement.

Bot Comment Evaluations

Gemini Code Assist suggested removing the warmup script after use (rm warmup.mjs) to reduce image size.

Priority: Not needed

The warmup script is very small (~600 bytes) and keeping it in the image aids debugging if there are issues with the compile cache in production. The space savings are negligible.

Status

No new issues identified. My previous review assessment stands: LGTM

The implementation is clean, well-documented, and follows Node.js best practices for compile cache usage.


Reviewed by Claude

@yamadashy yamadashy merged commit 32bf806 into main Jan 3, 2026
54 checks passed
@yamadashy yamadashy deleted the perf/website-server-compile-cache branch January 3, 2026 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant