Skip to content

Conversation

@NathanFlurry
Copy link
Member

No description provided.

@railway-app
Copy link

railway-app bot commented Jan 14, 2026

🚅 Deployed to the rivet-pr-3890 environment in rivet-frontend

Service Status Web Updated (UTC)
website ❌ Build Failed (View Logs) Web Jan 14, 2026 at 9:15 pm
frontend-cloud 😴 Sleeping (View Logs) Web Jan 14, 2026 at 9:12 pm
frontend-inspector ❌ Build Failed (View Logs) Web Jan 14, 2026 at 9:04 pm

@railway-app railway-app bot temporarily deployed to rivet-frontend / rivet-pr-3890 January 14, 2026 04:11 Destroyed
Copy link
Member Author

NathanFlurry commented Jan 14, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link

claude bot commented Jan 14, 2026

PR Review: Cloudflare Workers Support (DO NOT MERGE)

Overview

This PR adds support for running RivetKit on Cloudflare Workers without Durable Objects. The changes configure the chat-room example to connect to an external engine instance and handle request routing appropriately.


Code Quality & Best Practices

✅ Positive

  • Good commenting: The added configuration options in actors.ts have clear inline comments explaining each setting
  • Proper async handling: The server handler correctly uses async for the handler function

⚠️ Issues & Recommendations

1. Path manipulation could be more robust (examples/chat-room/src/server.ts:8)

const strippedPath = url.pathname.replace(/^\/api\/rivet/, "");
  • This regex doesn't anchor the end, so /api/rivet/api/rivet/foo would incorrectly become /api/rivet/foo
  • Consider: url.pathname.replace(/^\/api\/rivet(?=\/|$)/, "")
  • Better yet, if basePath is always "/", why not handle this at the framework level or make the route more specific?

2. Cloudflare Workers detection is fragile (rivetkit-typescript/packages/rivetkit/src/registry/index.ts:53-55)

const isCloudflareWorkers =
    typeof navigator \!== "undefined" &&
    navigator.userAgent === "Cloudflare-Workers";
  • User agent detection is brittle and can break if Cloudflare changes their worker runtime
  • Consider checking for Cloudflare-specific globals instead: typeof DurableObjectNamespace \!== "undefined" or similar
  • The check should be documented with why setTimeout isn't allowed in Cloudflare Workers global scope

3. wrangler.json formatting (examples/chat-room/wrangler.json)

  • File has inconsistent indentation (starts with spaces, mixed formatting)
  • Missing trailing newline
  • The placeholder "worker-name" should be updated to something meaningful like "rivet-chat-room" or documented as needing replacement

4. Hardcoded development URLs (examples/chat-room/src/actors.ts:30,40)

  • http://localhost:6420 and http://localhost:8787/api/rivet are hardcoded
  • For a proper implementation (even experimental), these should be environment variables or configuration
  • At minimum, add comments explaining these are development-only values

Potential Bugs

1. Request cloning potential issue (examples/chat-room/src/server.ts:10)

const modifiedRequest = new Request(url.toString(), c.req.raw);
  • Creating a new Request from the old one copies most properties, but the body stream can only be read once
  • If c.req.raw has already been read (unlikely in this flow, but possible), this will fail
  • Consider testing with POST/PUT requests with bodies to ensure this works correctly

2. Race condition in registry initialization (rivetkit-typescript/packages/rivetkit/src/registry/index.ts:56-61)

  • In Cloudflare Workers, the runtime won't auto-initialize via setTimeout
  • First request must trigger initialization, but there's no guarantee #ensureRuntime() is called before handler() is invoked
  • The handler() method does call #ensureRuntime(), so this should work, but the code comment implies auto-preparation is important for some reason

Performance Considerations

1. URL parsing on every request (examples/chat-room/src/server.ts:7-10)

  • Creating a new URL object and Request object for every request adds overhead
  • For high-traffic scenarios, consider if there's a way to configure basePath handling once rather than per-request

2. Runtime initialization

  • The #ensureRuntime() pattern with promise caching is good for avoiding multiple initializations
  • However, in Cloudflare Workers without the setTimeout, cold starts will include runtime initialization time on the first request

Security Concerns

1. Open CORS/origin handling

  • No validation of incoming requests or origin checking visible in this PR
  • If this is meant for production use (even experimental), consider adding request validation

2. Wildcard route handler (examples/chat-room/src/server.ts:5)

  • app.all("/api/rivet/*", ...) accepts all HTTP methods
  • Ensure the registry.handler properly validates allowed methods

Test Coverage

⚠️ No tests included

  • This PR adds new functionality but includes no test cases
  • At minimum, should test:
    • Path stripping logic with various inputs
    • Cloudflare Workers detection logic
    • Request handling with different HTTP methods and body content
    • Configuration validation

Configuration & Documentation

1. wrangler.json validation

  • Missing required fields for a complete wrangler configuration:
    • Should have node_compatibility or appropriate compat flags documented
    • Missing other typical fields like account_id (though those may be intentionally omitted for an example)

2. Setup instructions needed

  • How do developers run this? What engine needs to be running on port 6420?
  • How do they start the Cloudflare Worker locally?
  • This should be documented in the example README

Summary

This is clearly marked as "DO NOT MERGE" and appears to be experimental work. The core approach is sound, but there are several issues that should be addressed before this could be merged:

Must Fix:

  1. Cloudflare Workers detection mechanism (fragile user-agent check)
  2. wrangler.json formatting and placeholder values
  3. Add tests for new functionality
  4. Document the setup/usage process

Should Fix:

  1. Path manipulation regex (security/correctness)
  2. Hardcoded localhost URLs (make configurable)
  3. Consider URL/Request creation overhead

Nice to Have:

  1. Request validation/security hardening
  2. More robust error handling
  3. Performance optimizations for cold starts

Recommendation

Given the "DO NOT MERGE" status, this appears to be a proof-of-concept. Before this could be production-ready:

  1. Address the runtime detection fragility
  2. Add comprehensive tests
  3. Extract hardcoded values to configuration
  4. Document the setup process
  5. Consider whether the path-stripping approach is the right architectural choice

The code demonstrates a working approach but needs hardening for production use.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 14, 2026

More templates

@rivetkit/cloudflare-workers

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/cloudflare-workers@3890

@rivetkit/db

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/db@3890

@rivetkit/framework-base

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/framework-base@3890

@rivetkit/next-js

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/next-js@3890

@rivetkit/react

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/react@3890

rivetkit

pnpm add https://pkg.pr.new/rivet-dev/rivet/rivetkit@3890

@rivetkit/sql-loader

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/sql-loader@3890

@rivetkit/virtual-websocket

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/virtual-websocket@3890

@rivetkit/engine-runner

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner@3890

@rivetkit/engine-runner-protocol

pnpm add https://pkg.pr.new/rivet-dev/rivet/@rivetkit/engine-runner-protocol@3890

commit: 1c18fb1

@NathanFlurry NathanFlurry marked this pull request as ready for review January 14, 2026 07:27
@NathanFlurry NathanFlurry marked this pull request as draft January 14, 2026 08:19
@NathanFlurry NathanFlurry force-pushed the 01-13-do_not_merge_cloudflare_w_o_do_support branch from 4662ef8 to f35697e Compare January 14, 2026 08:21
@NathanFlurry NathanFlurry force-pushed the 01-13-chore_engine_provide_detailed_error_for_invalid_serverless_sse_event branch from 8e7fba5 to 41511a3 Compare January 14, 2026 08:21
@graphite-app graphite-app bot changed the base branch from 01-13-chore_engine_provide_detailed_error_for_invalid_serverless_sse_event to graphite-base/3890 January 14, 2026 20:53
@graphite-app graphite-app bot force-pushed the 01-13-do_not_merge_cloudflare_w_o_do_support branch from f35697e to 5f9f752 Compare January 14, 2026 20:53
@graphite-app graphite-app bot force-pushed the graphite-base/3890 branch from 41511a3 to 70158e8 Compare January 14, 2026 20:53
@graphite-app graphite-app bot changed the base branch from graphite-base/3890 to main January 14, 2026 20:54
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.

2 participants