Branch Bundles: better serverless support and infinite runtime scale #5405
Replies: 10 comments 21 replies
-
Beta Was this translation helpful? Give feedback.
-
This is... interesting. Cloudflare worker specific thoughts below :-D If you speak to most people deploying cloudflare workers they'll recommend combining many concerns into one worker ie. a nanoservice. This is beneficial for performance in that environment. This proposal does solve the issue of max worker size in this environment, which is good! But in order to get the maximum benefits these sub-workers should be invoked as services. This is a little difficult, but not impossible with workers, Pages would require a bit more thinking I believe as currently it's assumed that a remix app is a single pages function. |
Beta Was this translation helpful? Give feedback.
-
I have a concern about deploying updates. Deploying multiple lambdas/workers at the same time, in a transactional manner, sounds like a very tricky thing indeed. There is going to need to be some top-level lambda/worker or some CDN routing to switch between the old and new deployments I believe. This is verging on blue/green deployment territory. Introduces a lot of extra complexity to deployments in these environments. This is more of a comment for the teaching of this option, I think, as this kind of complexity is going to need to be explained in the docs and guides. |
Beta Was this translation helpful? Give feedback.
-
This is a very interesting proposal, but I have some thoughts as an AWS Lambda user. First of all, I am not super opposed to the fat lambda that gets deployed currently. It is a bit at odds with the least-privileged security model, but generally speaking, it keeps access patterns predictable to optimize provisioning for cold starts. I think a more workable alternative to this extreme is being able to opt into a separate bundle for a specific route, which should make sense after considering these points: Concerns
Possible Benefits
In summary, I think this approach adds a lot of complexity with very few possible benefits. I think a Happy Place for this idea could be opting for specific routes to get their own bundle instead of every route. This significantly reduces the complexity while still gaining the benefits in the majority of cases. It's much easier to decide that the PDF generating route should be tuned separately from the rest of the app, or the payment processing route can have secrets separate from the rest of the app, or the image processing library can be loaded for a specific route but excluded from the bundle for the rest of the app. |
Beta Was this translation helpful? Give feedback.
-
If it will be possible to branch specific routes it will be amazing. |
Beta Was this translation helpful? Give feedback.
-
The I'm calling it serverBundles: [
{ serverBuildPath: 'build/build1.js', routes: ['routes/index', 'routes/about'] },
{ serverBuildPath: 'build/build2.js', routes: ['routes/generate', 'routes/error'] }
],
This is actually more low-level than Let me know what you think, I hope you like 😄 |
Beta Was this translation helpful? Give feedback.
-
From reading the concerns mentioned above, it seems edge platforms that support safe multi functions deployment will benefit the most from this feature. Such as Vercel Edge Functions and Netlify Edge Functions. The reasons are:
Therefore, I want to propose additional changes to better fulfill the requirements of those platforms. I will use Vercel Edge Function with Vercel Build Output API v3 as the imaginary constraints to demonstrate the proposal in action. Taken from Vercel Build Output API docs for edge functions, below is the required file system structure:
We need a way to customize the placement of each server bundle and also emit other files that are required by the platform such as
Personally, I prefer the first solution because it is clear what to expect from the option name. Also, for consistency sake, I think |
Beta Was this translation helpful? Give feedback.
-
This proposal would be very appreciated. I really like the idea of @TooTallNate #5405 (comment) so that multiple routes can be bundled together or splitted out into separate files. having a mix of serverless node functions and edge functions on vercel would greatly benefit from that. Edge functions have no cold start so they can be split into separate functions. Serverless functions suffer from cold starts so they can be bundled together Edit: + we have a working POC of this made by @TooTallNate |
Beta Was this translation helpful? Give feedback.
-
I'm very interested in this functionality. Additionally, I wonder how hard it is to implement in userland. I've seen the routes split when deploying to Vercel but no idea how they do that. |
Beta Was this translation helpful? Give feedback.
-
This seems to be related to React Router Roadmap |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
tl;dr
Background
The ethos of serverless is to have small functions, not the whole app, on each function. This is good for UX to speed up cold boots, good for developers for debugging (logs are function specific, etc.), and resilience (one function might be busted but the others aren't). There are a bunch of other reasons too but that's all barely inside my wheelhouse, so I don't have much more to say other than that.
Point is, we could support serverless much better than we do today with Branch Bundles.
Proposal
remix build --branch
Instead of creating a single server bundle, this would generate a server bundle for every branch of the route tree. Each of these branches could then be deployed to a separate lambda.
Consider the following routes:
This would result in the following server bundles:
The name is irrelevant (though we might want a convention to make it easy to set up your infrastructure), it's just to illustrate the code contained in each bundle. While it looks like they're just the bundle for every route, they will actually contain the code of the parent routes as well. For example,
root--account--orders--$oid.js
would have all four routes bundled into it. Similarly,root--account--order.js
would be identical except it would not include$oid.js
.Each bundle needs the parent routes because all parent routes are needed to render a full HTML document.
Once these bundles are created, you'd need to set up your infrastructure to deploy each bundle to its own lambda and serve the right lambda for different URLs to the app (I've done this with arc and it's easy but verbose, for vercel we'd probably build into their file system
.build
API, not sure what netlify looks like).Since each bundle also needs the server module that sets up an adapter, we'd probably want to make that part of the bundling process, too.
Pretty much infinite runtime scale here with this and serverless. No route branch will ever get tremendously big because they are naturally restricted to the cognitive processing of a human looking at the screen. While apps can grow enormous in breadth, routes have a natural depth size limit because it represents a single UI the user is looking at.
I know the Vercel team is very interested in this, maybe we can get their help with the work.
Beta Was this translation helpful? Give feedback.
All reactions