vaadin / hilla

Build better business applications, faster. No more juggling REST endpoints or deciphering GraphQL queries. Hilla seamlessly connects Spring Boot and React to accelerate application development.
https://hilla.dev
Apache License 2.0
906 stars 57 forks source link

Deploy backend and frontend separately #896

Open tarekoraby opened 1 year ago

tarekoraby commented 1 year ago

Hilla requires the backend and frontend to be deployed together as a single Java bundle. However, the cost of deploying Java is considerably higher than deploying a React app (the latter can be deployed to object storages like AWS S3). Moreover, for pure client-side changes, it would be redundant to redeploy the Java parts of the App.

For these reasons, consider adding support for deploying the frontend and backend separately in Hilla. I say "consider" because I'm unsure how to solve the possible issues related to API mismatch if the frontend and backend are allowed to be deployed separately.

Legioth commented 1 year ago

One hypothetical benefit that would be unlocked is the possibility of distributing the frontend files through a CDN so that they would be closer to the user's location. This is usually not critical for business applications but might still be relevant in some cases.

the cost of deploying Java is considerably higher than deploying a React app

Can this cost be quantified? Since you already need to deploy a Java backend for the endpoints, I would assume that there's a very small incremental cost from also making that Java app contain and serve some static files for the frontend.

Moreover, for pure client-side changes, it would be redundant to redeploy the Java parts of the App.

You need extra complexity to benefit from this since you need to also have some logic that keeps track of which parts have changed to be able to know which parts need redeploying.

marcushellberg commented 1 year ago

If we split up the deployment, could we deploy the endpoints as serverless functions, similar to what Vercel does with Next.js? Would there be any benefits to that?

tarekoraby commented 1 year ago

Can this cost be quantified?

I can't quantify it. But, for example, AWS CloudFront is free for the first 1 TB of monthly data transfer. Anything that's completely free is hard to resist for many (even if a single deployment of Java + frontend will be only marginally more costly than separate deployments).

If we split up the deployment, could we deploy the endpoints as serverless functions, similar to what Vercel does with Next.js? Would there be any benefits to that?

To my understanding, @Artur- has already demonstrated that deploying Hilla to serverless functions is possible. But yes, it would make more sense to serve the static frontend bundle from a CDN or storage instead of firing a serverless function just to download the frontend.

Legioth commented 1 year ago

Anything that's completely free is hard to resist

What matters is the total cost of running the whole application. If you (hypothetically, since I'm totally making up numbers here) pay $100 per month for serving endpoint requests, then it doesn't matter so much whether the monthly cost for serving static resources is $1 or completely free. Even a single hour of extra work to configure a more complicated deployment setup would take years to pay back in that scenario (and that's assuming there won't be any additional maintenance needs after initial setup).

The idea of deploying static resources separately comes from consumer-facing systems with lots of traffic and relatively little server-side interactivity. There you have a higher static:dynamic cost ratio than the 1:100 that I suggested (based on nothing particular) and also a higher absolute cost for hosting. It also has some undertones of different parts owned by separate teams with REST endpoints that are used by multiple clients which again leads us to a different discussion.

I you still have a need to optimize static resources serving, then you also have the option of putting a CDN proxy such as Cloudflare in front of the whole application instead of splitting up the deployment. I don't have insights on which approach is better in which cases, but I do at least know that Cloudflare is a very popular choice in general.

If we split up the deployment, could we deploy the endpoints as serverless functions

I don't see why we couldn't do that even without splitting up the deployment. If we assume that any page load or user interaction triggering more JS to be lazy loaded also triggers an endpoint call, then there wouldn't even be any redundant cases of spinning up something only for serving a static resource since the same instance would very soon also receive endpoint requests.

I expect that a separately deployed frontend would just slightly reduce the load on the serverless function which means that you could handle more users with only a single instance (or spend slightly more time with no instance running at all). At the same time, the extra load for handling some static resources is probably so small that the impact would be relatively marginal (assuming a "real" use case where business logic triggered through endpoints would outweigh the static resource handling).

tarekoraby commented 1 year ago

What matters is the total cost of running the whole application ...

That may be true if one is being strictly rational. Humans aren't always rational, and the warm feeling some people get from optimizations and cost savings (even if those are minimal) can trump rational calculus.

marcushellberg commented 1 year ago

Besides just cost alone, we should also consider organizational fit. If a company has set up its deployments in a way that they deploy frontends and backends separately, they may not want to have one app deployed differently. If their deployment block game only has round holes, they may not care if our square block is better on a rational level.

Legioth commented 1 year ago

If a company has set up its deployments in a way that they deploy frontends and backends separately, they may not want to have one app deployed differently.

It might be useful to understand more about how common case that is and whether that kind of setup is also associated with a mindset to have generic REST endpoints that are used by multiple clients?

enryold commented 3 months ago

The main issue is the fixed cost of maintaining a small project with little traffic. I used to have a react app deployed on AWS S3 with Cloudfront in front of it and AWS Lambda for APIs in the backend. The cost was less than $ per month because of the small traffic and AWS Lambda's 1 M free monthly requests.

I'm running a Vaadin app on AWS App Runner with minimum traffic, and it's 20/month.

BTW, I'm Interested in @Artur- hilla + serverless tests. Can you share something?

Legioth commented 3 months ago

Could the static files be served by Lambda? The number of additional requests might be low enough to not have a big impact. Alternatively, something like Cloudflare could be used in front of the whole thing if configured to only cache requests to the paths containing static files.

enryold commented 3 months ago

I think static files could be served as well with some trick on the lambda handler, that’s why I asked if there’s some example I can check. Yes I agree on caching, on AWS you can add Lambda as Origin in Cloudfront CDN and cache content by path.