parse-server
parse-server copied to clipboard
Parse Server compatibility with Serverless environment
New Feature / Enhancement Checklist
- [x] I am not disclosing a vulnerability.
- [x] I am not just asking a question.
- [x] I have searched through existing issues.
Current Limitation
I'm currently investigating the usage of Parse Server in a serverless env. The current tested setup is:
- Parse Server with Defined Schema and GraphQL packaged in a Docker image
- This Docker image is used on Google Cloud Run, with CPU allocated only during init/requests
- Use MongoDB Atlas Serverless as the database
Refactors/workarounds:
- Parse Server express app call
listen()
too early (before serverStartComplete), so request cloud be routed to parse-server with a partial/incomplete initialization. For example, defined schema migration could not be finished. A workaround is to call a new "parse.expressApp.listen(1339)" on a different port in serverStartComplete to tell the serverless env (GCP Cloud Run) to start sending requests to the 1339 port.
Errors:
- Mongo Collation on Serverless service, reported here: https://github.com/parse-community/parse-server/issues/7937
Limitations:
- On many serverless env background tasks (actions performed after a request is returned by the server): like Parse.Jobs will not work
- LiveQuery needs an additional setup (not tested)
Stats:
- Parse Server with defined schema start in 7sec when Parse needs to create all schema (should only happen one time)
- Parse Server with defined schema start in 3-4sec when Parse is already initialized (defined schema done, DB init done, etc...), this is the real cold start if Parse Server scale to 0 instances.
Feature / Enhancement Description
The cold start is mainly related to dependency size. To reduce cold start we need to start some code splitting. All adapters should be moved out of parse-server. Developers should be able to only import wanted adapters/servers, like LiveQuery, GraphQL server, PostgresAdapter, etc...
Then some tiny cache optimization could help to make the parse-server start under maybe 1-2sec.
Example Use Case
Fully serverless usage (with mongo serverless) to allow Parse developers to leverage Serverless computing like:
- No infra management
- Super scalable
- Scale to Zero
- Huge cloud cost reduction
Alternatives / Workarounds
None
3rd Party References
Cloud providers that support scale to zero container instances
https://cloud.google.com/run https://www.scaleway.com/en/serverless-containers/ https://docs.microsoft.com/en-us/azure/container-apps/ https://aws.amazon.com/ecs/
Database provider with serverless (pay as you go) pricing https://www.mongodb.com/cloud/atlas/serverless
Thanks for opening this issue!
- 🎉 We are excited about your ideas for improvement!
See https://github.com/parse-community/parse-server/issues/483
Note: I'm currently not investigating proprietary serverless environments like AWS Lambda/Cloudflare Workers/Vercel serverless. Since it needs specific adaptations/bundling, it's not easily testable in a local env. From my point of view, it's a less standard approach.
Docker helps to get some execution abstraction.
I'm currently focusing on making a parse-server at least compatible to run in a container on a serverless orchestrator: like GCP Cloud Run, Knative.
I'm also focusing on containers since Knative is now part of CNCF, and could be the next cloud standard (like Kubernetes ) to deploy serverless containers across cloud providers: https://www.forbes.com/sites/janakirammsv/2022/03/06/cncf-accepts-knative-projectwhat-does-it-mean-to-the-cloud-native-ecosystem/?sh=72413dfe174b
So is this still a general discussion? In that case it should continue in our community forum. We use GitHub to track concrete issues and feature suggestions.
It's not a general discussion, it's an issue, and I will work on a PR to fix the app. listen to the issue. I'll also work on a distinct pr to fix the collation issue for Mongo Serverless.
What you are describing seems to be a refactoring of Parse Server that won't be done with a few small PRs. These seems to be several individual issues (adapters, cache, collation), each of which will likely require its own GH issue and discussion. Could you make a roadmap for this with a TODO list to see for which points we need to discuss in more depth?
@mtrezza
Roadmap:
Minimum compatibility requirements
- Fix errors (developers do not have workarounds):
- feat: allow to disable collation (case-insensitivity) on User queries/indexes (email/username)
- Parse Server listens too early
- feat: add a new "startCompletePort" option to be handle correctly public requests (from a internet/balancer) once parse server startComplete resolve. We need an additional port since internal parse-server code, developers' code inside before/afterMigration, and startServerComplete could use Parse Node JS SDK that internally uses a serverUrl.
At this point Parse Server (without livequery and Parse Jobs) should be able to run in a containerized serverless env out of the box (for example on Cloud Run GCP)
Performance improvement (road to 1-2 sec cold start)
- Code splitting
- feat: move out adapters of the parse-server package, and allow developers to only install and provide needed adapters, to reduce nodeJS require time currently approximatively 2sec
- Init speed up
- feat: use the hash (SHA1) mechanism on schema and some configs to easily detect changes, I think parse-server could be optimized and can reduce init time.
- Dynamic module loading investigation
- feat: some modules of parse could be required dynamically once needed, for example, an auth provider, should be loaded only if a request uses it. The server should not load/require all the code by default at startup time.
Support feature not "Serverless Friendly" like LiveQuery, Parse Jobs
- feat: test and support LiveQuery limitations on serverless
- feat: (i need some investigation on this) add "serverless" Parse Job option, if activated, when a job is triggered from a client (ex: parse-dashboard), to be able to handle the background job, parse-server will need to call itself or another parse-server instance via parseServerJobPublicURL, since many serverless environments only attribute CPU during a request (like GCP). The new jobServerlessEndpoint need to await job completion before returning an HTTP response, to keep access to the CPU. The parseServerJobPublicURL could be also used to allow developers to run Jobs on a dedicated remote parse-server, not running in serverless env.
@mtrezza we can split this one into many issues. I think we should also keep this issue open to tracking the work progress.
I'll work on point 1 and 2 may be the next week?
Yes, this should be split into smaller PRs as much as possible because large, monolithic PRs are more difficult to manage and take more time to get merged. We can keep this issue open to track the progress; maybe you want to move a compact TODO list of your roadmap to the post at the very top and add checkboxes and PR references to each one so everyone can easily see the status of this.
Just for reference, the readiness probe, exposing the server to public traffic needs to be handled by the developer.
Linked comment : https://github.com/parse-community/parse-server/pull/7914#issuecomment-1115902685
The https://github.com/parse-community/parse-server/pull/7914 will allow developers to design graceful start easily using startAsync
or serverStartComplete
thanks to @dblythy
@mtrezza what do you think about adding a section on the docs about some tips for a graceful start in environments like PM2, GCP Could Run, Kubernetes, etc...
Sure, please feel free to open a PR.
👀 I'm also interested in serverless hosting, specifically Atlas Serverless... I'm curious to know what the status of this project is.
Hi @stewones, I'm running successfully many parse servers with MongoDB Atlas Serverless (6.1). Once correct indexes are added it works like a charm with excellent cost efficiency.
To work with MongoDB serverless some PRs are needed like this one: https://github.com/parse-community/parse-server/pull/8042
The best and easiest option to run parse-server
in serverless env is Google Cloud Run using a Docker container.
@mtrezza once needed PR to are merged I can push a repo example (with terraform file example) to deploy Parse Server fully serverless on Google Cloud Run and Mongo Atlas Serverless for developers interested in running parse-server as Serverless.
The repo example could be coupled to a documentation page/blog post maybe
it could be a good blog post for Parse V6: "Parse Server goes fully serverless with Mongo Atlas Serverless and Google Cloud Run"
@dblythy do you have some suggestions here ?
It sounds like a good idea. Mongo Atlas Serverless sounds exciting and I'm keen to see how it compares in price vs my current solution which is AWS EB.
I'm keen to see how it compares in price
On MongoDB Serverless it depends a lot of indexes, a poorly indexed query will produce a lot RPU, my current strategy is to "over-index" (creating many indexes on possible queries) since storage is so much cheaper than RPU/WPU.
But I can easily say that once indexes are correctly configured, scaling, performance, and cost of MongoDB Serverless are really impressive.
And Parse Server on Cloud Run with a Google Cloud task that keeps at least 1 server idle, it's also really cost-efficient.
@dblythy
For an app with invariant traffic and 10k of users you can easily run Parse Server on Cloud Run + Mongo Atlas Serverless for like 10$/month (or less) (but it really depends of the app, and optimization, caches etc...). Serverless is not magic, just super efficient when it's correctly used.