[HN Gopher] Edge-compatible Serverless Driver for Postgres
___________________________________________________________________
Edge-compatible Serverless Driver for Postgres
Author : carlsverre
Score : 53 points
Date : 2022-12-08 16:18 UTC (6 hours ago)
(HTM) web link (neon.tech)
(TXT) w3m dump (neon.tech)
| nikita wrote:
| I'm Neon CEO. Happy to answer questions. We also have an
| interesting roadmap for the driver where we hope to keep driving
| latency and number of round trips down
| krashidov wrote:
| Hey Nikita, what are the key differences between neon and
| Supabase?
| nikita wrote:
| I think we innovate on different parts of the stack. Neon is
| offering separation of storage and compute and serverless.
| Theoretically you can run Supabase on top of Neon
| nikita wrote:
| To elaborate Neon is designed deliberately to plug into the
| Postgres ecosystem. So all of the ecosystem works out of
| the box. Supabase seems to be vertically integrated. But
| Paul should comment on that
| kiwicopple wrote:
| I believe most of the tools that Supabase use would work
| with Neon, with the exception of Realtime. As I
| understand it, Neon doesn't support Logical Decoding
| yet[0], which is required so that the Realtime engine can
| receive updates from the database.
|
| [0] https://community.neon.tech/t/plans-for-logical-
| replication/...
| nikita wrote:
| You are right. We will make it work soon
| sakras wrote:
| I'm curious why not implement websockets into Postgres natively
| instead of relying on a proxy server? Wouldn't that be the way
| to minimize latency?
| neuronexmachina wrote:
| Being able to connect to arbitrary Postgres servers (or
| potentially even the postgres compatibility-layers for AWS's
| Aurora or Google's AlloyDB) seems like a good reason to go
| for the proxy approach.
| nikita wrote:
| Yes. Also it was an easier thing to do and ship quickly. We
| are going to get very tight on latencies and if that would
| require building it into Postgres we will do so
| pbiggar wrote:
| Does Neon scale down storage? I'm paying GCP a lot for storage
| I don't use, and it's incredibly frustrating - they scaled me
| up no problem but won't let me scale down.
| nikita wrote:
| Storage is multi tenant and bottomless. Unused storage spills
| to S3 and is cheaper. We pass savings to our users
| pbiggar wrote:
| I think you're telling me the answer but I amn't sure.
|
| Suppose I use 10TB of storage, and then later I delete all
| but 100GB of storage. Will I be paying for 10TB or 100GB?
| nikita wrote:
| 100GB
| jtmarmon wrote:
| Would be really cool to see you guys become a managed service
| on Fly.io - see what they did with Upstash & Redis:
|
| https://community.fly.io/t/preview-managed-upstash-redis-wit...
|
| They don't have a managed postgres offering yet ("this is not a
| managed postgres" - https://fly.io/docs/postgres/getting-
| started/what-you-should...)
| bilalq wrote:
| I don't see pricing listed anywhere. Can you expand on what
| that might look like? Also, can Neon scale down to zero like
| serverless aurora v1, or is there a minimum capacity unit?
| nikita wrote:
| Pricing is coming very soon. Dotting the is and crossing the
| ts
| nikita wrote:
| And yes. Scales to 0
| canadiantim wrote:
| Would it ever be possible to run neon on a mobile phone, offline?
| nikita wrote:
| We have some ideas of compiling Postgres to wasm and sync with
| the mothership in the cloud. But we haven't funded the work.
| Check out electricsql they are looking at this problem.
| thruflo wrote:
| Hey, link for the curious: https://electric-sql.com
|
| Hybrid serverless <> local-first is the future. Neon in the
| client would be so cool.
| dboreham wrote:
| Hmm. Wouldn't this also be useful for browser-hosted application
| code that wants to talk to PG directly?
| kelvich wrote:
| Right, that is one of the use cases. Auth is tricky part in
| that setup -- in the browser user may change the query in
| arbitrary way. But there are some workarounds like obtaining
| JWT from 3rd party service and checking it via Row-Level
| Security policy in Postgres.
| Sujan wrote:
| The "How it works" section surprised me - I did not expect to see
| Websockets there.
|
| Other serverless drivers or database APIs (PlanetScale Serverless
| Driver, AWS RDS Proxy or Prisma Data Proxy) usually use HTTP to
| replace the stateful TCP connection. The post explains a bit why
| this might be beneficial (can use existing tools, and use
| connection state) - but what about the other benefits and use
| cases of going with HTTP?
|
| For example in that architecture the connection pool also moves
| from the application to the component in between and all that
| complexity can completely be removed from the app. Especially on
| serverless platforms, where in theory each request gets its own
| application with its own pool, that is huge. How does that work
| here? Or does the pool also move to the "WebSocket-to-TCP proxy"
| and you just did not highlight it in the post? (The graphic shows
| a "Connection Pool" but I can not really make sense of what that
| means.)
| mattashii wrote:
| HTTP does not (easily) allow for using answers of earlier
| queries in the transaction. E.g. BEGIN;
| INSERT INTO my_table (...) RETURNING (id); SELECT
| count(\*) AS my_count FROM my_table; INSERT INTO
| historical (new_id, value_derived_from_count, now());
| COMMIT;
|
| is difficult (or potentially impossible) to do transactionally
| using single HTTP queries. Sure, you can rewrite your queries
| to use single-statement queries if you're lucky, but for others
| that may take a lot of work. Keeping a transaction alive over
| WebSocket allows you to easily have transaction states that
| last longer than the lifetime of the first request, which
| allows for transactions of which state is processed in more
| than one place.
| rhyselsmore wrote:
| Just turn it into a single query using CTEs.
| Sujan wrote:
| That I understand.
|
| But of course for the user of the driver it might be fine if
| that is 2 or more HTTP requests. I expect that is how
| PlanetScale does it in their transaction implementation,
| https://github.com/planetscale/database-js#transactions, and
| I know that is how Prisma Data Proxy handles it - the
| transaction is identified with an ID which is returned to the
| Client and then included in further requests for the same
| transaction.
|
| It's valid tradeoff to make to prefer a persistent connection
| to keep the overhead for multiple queries in a transaction as
| low as possible - which seems what Neon has done here.
| throwdown220 wrote:
| It's not a trade off. They've not been able to do something
| that is doable and are trying to tell you it is a trade
| off.
| mattashii wrote:
| > the transaction is identified with an ID which is
| returned to the Client and then included in further
| requests for the same transaction.
|
| Yes, and there's a catch there that people might not
| notice: HTTP-based queries utilize this ID to identify
| which active transaction to use, but this is vulnerable to
| concurrent HTTP requests on the same transaction ID, thus
| allowing query injection (early COMMIT, SELECT
| sleep(1000000), etc. by attackers) due to requests being
| re-routed every time you send the query.
|
| Keeping a direct connection (albeit proxied) to the
| PostgreSQL instance prevents this kind of attack, while
| also allowing for better state keeping control in systems
| that don't have access to raw TCP sockets, and reducing
| per-query overheads.
| mattrobenolt wrote:
| In our case, it's a bit more state than just a
| transaction ID, but the same concept applies.
|
| And yeah, to mirror the other comment, this isn't
| particularly something I'd consider a security issue. If
| an attacker has access to your transaction (session)
| state, this is a similar risk vector on any web service
| that utilizes browser cookies or sessions. If someone
| hijacks your browser cookies, they can do anything they
| want into your account typically, ignoring 2FA and extra
| layers.
|
| Same risk here. If someone were to intercept your
| request, which is strictly over HTTPS, and hijack your
| session, or you erroneously were logging the session and
| authentication credentials publicly, then you're exposing
| yourself to a lot bigger risk than someone adding a
| sleep() into your session. They could just dump
| everything from the database, because they are you.
|
| A direct connection only changes this because it's a
| stateful protocol, and if the connection is severed,
| everything is lost/rolled back and nobody can intercept
| that.
|
| But anyways, I'd hardly call a well established security
| model of HTTP sessions flawed in this regard.
|
| If anything, it's possible for a client to do some dumb
| things, like, parallel queries within a single
| transaction, which you cannot do with a direct
| connection, which ultimately is just... going to be
| undefined behavior since they fundamentally get
| serialized into the database, just in an undeterministic
| order relative to the client.
| [deleted]
| Sujan wrote:
| I am not sure I am following.
|
| We can have either parallel queries in a transaction
| where the order does not matter, or we can have them
| serialized - but then the next query will only be sent
| onto its journey after the previous query returned its
| data to the app.
|
| What are the attack vectors here? And where would the
| attacker sit and try to achieve what exactly?
| kelvich wrote:
| Another angle here is compatibility. With our current driver
| one can use ordinary node-postgres package, as we can
| substitute TCP-related calls with WebSocket calls during the
| build time. With that it possible to use all the packages that
| do require node-postgres like Prisma, Zapatos, etc.
| Sujan wrote:
| Prisma does not actually use node-postgres, but a Rust
| PostgreSQL driver. Prisma will not be able to use the Neon
| serverless driver.
| kelvich wrote:
| https://github.com/prisma/prisma/blob/main/packages/client/
| p...
| Sujan wrote:
| That is only used in tests :) The query engine uses this:
| https://github.com/prisma/quaint/blob/6532d69b5aec007ad06
| ac6...
|
| (I work at Prisma, could have mentioned that earlier)
| kelvich wrote:
| Gotcha. I drew my conclusion based on the mentioned
| package.json. Now wonder why did you decide to go with
| rust for query engine? Do you compile it into wasm?
| Sujan wrote:
| It made sense at the time. We do not only support Node,
| but also have community Clients in Go, Python or Rust.
| Right now we are moving more and more parts from a Node-
| API library or binary engine (the two variants we support
| until now) over to Wasm modules where it is possible for
| our Node/TS/JS Client. Socket/TCP connections itself are
| unfortunately not supported yet, so this will only be
| partial. And maybe there is also a future where we
| support Node based databases drives. As this blog post we
| are commenting on shows, sometimes we have to combine the
| weirdest things together to achieve our goal.
| gmac wrote:
| Right: at a basic level, using WebSockets lets us change as
| little as possible from the user perspective. You get an
| ordinary Postgres session with an ordinary Postgres driver,
| full control over transactions, and so on.
|
| At this point, your serverless function establishes a new
| Postgres connection on each call. We do pooling on the server
| side with pgBouncer, which means we can handle lots of
| simultaneous connections (which is what this approach
| generates). It's true that this approach doesn't fully optimise
| for low latencies. But, as Nikita has mentioned elsewhere in
| this thread, we have a roadmap for bringing latency down in a
| number of different ways over time.
| Sujan wrote:
| Ok, so to make that explicit: If I want to do 5 parallel
| queries on my serverless function I should still have a
| connection pool size of 5 in my application, which will be
| fine as PgBouncer ensures there are plenty connections to
| open and use from the database server side. Correct?
| gmac wrote:
| In principle, yes, but as things stand you'll be starting 5
| separate TLS connections to the server that way. My feeling
| is that this would be an unusual way to use serverless
| functions. Is it something you think you'd do?
| Sujan wrote:
| Yes. You only have to open these connections once on the
| first execution of that function (cold start), any future
| request that hit this warm function will have 5 open
| connections and can instantly execute these queries in
| parallel. No overhead at all to open the connections.
|
| What would be the alternative? Only execute the queries
| in sequence, one by one?
| vojtad wrote:
| Just for the recerence, it is possible to use Cloudflare Tunnel
| to connect to Postgres from Cloudflare Workers [1]. IIRC they
| also use WebSockets for communication between the Worker and the
| Tunnel.
|
| [1] https://developers.cloudflare.com/workers/tutorials/query-
| po...
___________________________________________________________________
(page generated 2022-12-08 23:01 UTC)