9 ms·
Show HN: GraphCDN – GraphQL CDN with edge caching and analytics
- andrewingram 5y agoI asked Max in private, but i'll ask again here for visibility. How do you handle smart invalidation? Or more specifically, how do I trust that you're handling smart invalidation _correctly_. Looking at the site, it indicates that calling a mutation like `editUser(id: 5)` would presumably invalidate the User type record with ID 5. But how do you actually do this reliably? There's nothing in the spec that would indicate the argument ID maps to a record of a certain type with an id field of the same value. Max indicated that you make assumptions based on the return type of the mutation, e.g. editUser has a return type of User, therefore you can infer the relationship. This might be _generally_ true, but it's not 100% reliably true. Additionally, my mutations _never_ just return the naked entity type like this, there's always a wrapping payload type (philosophically, the mutation payload should contain points to all the parts of the graph that _may_ have changed as a result of the operation). Editing a User doesn't _just_ edit a User, the effects on the graph can propagate far and wide. Another point here is that my mutations are rarely just CRUD operations, but more CQRS in nature, they're built to support a specific system capability rather than allowing generic write operations. The problem of smart invalidation seems to have the exact same shape as smart store invalidation/updates after a mutation in the client. Even after all these years, Relay only does fairly superficial automatic updates, you nearly always have to use custom updaters (or client-side directives in some cases) to get the client-side store back in sync after anything but the most trivial mutations.
- mxstbr 5y agoGreat questions Andy! We do support wrapping payload types of any kind because we invalidate _all_ objects returned from a mutation. For example, if you run a mutation like editUser { user { id posts { id } } } we will invalidate any cached query result that contains that user and any cached query result that contains any of those posts! You are right that smart invalidation can never be 100% reliable, which is why we have the Purging API to manually purge records you know changed from your backend. I think most customers are going to use the manual Purging API, however we also have a bunch of customers with use cases for whom the smart invalidation suffices.
- jorams 5y agoI guess that means a mutation like `editUser { user { name } }` would not trigger smart invalidation, since there is no ID to work with?
- mxstbr 5y agoThat's correct, however we also allow defining custom "Key fields", which is how you can tell us which fields are unique and should be invalidated by (e.g. "User.email").
- nivertech 5y agoWould UUIDs or Relay-style global IDs help to avoid manual purging here?
- mxstbr 5y agoAny kind of unique ID works, whether UUIDs, global IDs, incremented IDs, etc.
- habibur 5y agoRather the API client calls the invalidation methods on the server to invalidate cache. The server doesn't do it all automatically. As far as I have understood.
- timsuchanek 5y agoThat sounds correct! These are ways of purging we support today: 1. Automatic through mutations (if we can detect) 2. A purging api (GraphQL) - you can e.g. `purgeUser(id: 5)` 3. The usual Max age + SWR based invalidation You can check out some more examples here: https://graphcdn.io/docs/cache-purging https://graphcdn.io/docs/cache-purging
- pistoriusp 5y agoThis is such a great idea! There are a lot of plays in this space that try to move the database, or serverless-functions closer to the end-users, but in all likeliness if you're already building a single-page-app the static content is already on a CDN and close to your customers, so this gives you a very easy way to increase performance dramatically without having to modify your infrastructure. Awesome!
- timsuchanek 5y agoThanks Peter! Yes, we also think that there is a lot of exciting stuff happening in the space. However, we built GraphCDN because we think it's a very practical approach _today_. I think it will take a couple of years until edge compute becomes mainstream. You need your whole database etc on the edge, otherwise it doesn't make sense. So we're happy about this level of abstraction, because any app can use it _today_!
- mxstbr 5y agoHey HN, When I built my last startup, Spectrum, we spent months building custom caching for our GraphQL API from scratch. It never worked well enough to alleviate our scaling troubles as we could only cache data for unauthenticated users since we had no invalidation. (since we open sourced it all before GitHub acquired us, you can even read through my terrible code[0]) When Tim told me he had built a prototype of a CDN specifically for caching GraphQL query results with proper invalidation, my first thought was: "Finally!" Not only had he made it possible to cache POST requests (which GraphQL requests usually are), he had made it possible to purge cached query results per specific GraphQL object. For example, when a user edits their name the API can call a purgeUser(id: $ID) mutation and any cached query result that contains that user's data is invalidated. GraphCDN is based on Fastly Compute@Edge under the hood, which is really the main reason we were able to spin this up so quickly. Huge shoutout to the folks building that! We'll be around all day to answer any questions you have about GraphCDN — ask us anything! [0]: https://github.com/withspectrum/spectrum/blob/alpha/api/apollo-server.js https://github.com/withspectrum/spectrum/blob/alpha/api/apol...
- cpursley 5y agoReally interesting. Can this work with Hasura?
- timsuchanek 5y agoYes, it does! We have more and more people who want a more powerful cache setup than what Hasura offers or are just self-hosting Hasura. Both self-hosted and Hasura cloud work!
- cpursley 5y agoShut up and take my money! This will save me a bunch of time from my original plan of rolling a distributed Elixir proxy caching cluster to put in front of Hasura. I'd love to see a write up/blog post for working specifically with Hasura and their auth system. Would probably be helpful for seo purposes as well.
- sergiotapia 5y agoDo you have support for HIPAA/SOC2 companies? We have PII/PHI and would love to use this.
- mxstbr 5y agoWe don't currently have the certifications, but they are high up on our roadmap! Send me an email about this to max@graphcdn.io and I will ping you once we are there.
- timsuchanek 5y agoHey HN, It's a pleasure to share this announcement with you! In all the GraphQL projects I worked on, it was always a pain to get the caching and security right. Instead of you all spending time on building your own caching and security solutions, you can check out GraphCDN! It has powerful caching with invalidation in 150ms all around the planet. Powerful analytics showing you on a Query-level, how fast your queries are. We're super grateful to be able to announce this today - ask us anything!
- tcmb 5y agoSounds cool! I‘d be interested in the caching and analytics part, but without the CDN, i.e. for an internal GraphQL server. Is there a way to do that?
- mxstbr 5y agoWe are based on Fastly Compute@Edge, so we can't currently offer an on-prem solution unfortunately.
- benjamoon 5y agoLooks really good, well done! Just fyi, I noticed my phone (new iPhone) got really hot when looking at your site. I’ve had this before on sites and it’s usually a bug or a really tight loop somewhere that’s causing high cpu usage (maybe the animations). Sometimes it’s not high enough to notice on a laptop or full pc, but it’s enough to warm up a phone.
- timsuchanek 5y agoThanks a lot benjamoon ! It probably is the main animation on the landing page. We'll look into it - maybe we'll just disable the animation on mobile.
- deergomoo 5y agoSafari has a long-standing bug where animated SVGs chew up CPU cycles like they're going out of fashion. Happens on desktop too.
- 0xy 5y agoI don't see any mention of support for subscriptions on your website. Is that currently supported or is it on the roadmap? Also to seed an idea for you, it'd be great if you were somehow able to provide subscriptions dynamically based upon queries and mutations being performed. Acting as the middleman, you can see the freshest data and so therefore know when something updates. If I could hook that up to my existing GraphQL API and not have to worry about eventing and subscription services for every single object that would be a huge value add for me.
- mxstbr 5y agoWe support subscriptions, meaning we pass through "Upgrade" requests to your origin and they will keep working as they were before! "Automatic subscriptions" is definitely something we've considered offering, but isn't on the immediate roadmap for now as we want to focus on the "peace of mind" first before expanding from there.
- joshenders 5y agoCritical feedback: This seems like a product with an exceptionally shallow moat. What is stopping Cloudflare and Fastly from cloning and burying?
- timsuchanek 5y agoOn the first sight, the moat indeed is shallow. We have a great contact with Cloudflare and Fastly and exchanged our thoughts about exactly this already. One of them actually recently looked into building their own solution. However, they realized, that in order to create something really valuable, you need at least a couple of months of dedicated engineering efforts of people who really understand GraphQL. Our automatic and powerful cache invalidation - currently only possible with Fastly, a whole GraphQL-specific Analytics solution and a Security suite is nothing you can quickly clone. Anyone of course can, but you need a highly GraphQL-specific product with many workflows like CLI workflows to upload your GraphQL Schema etc - it requires quite a bit of thinking and engineering to make that work.
- joshenders 5y agoLet me start off by saying, I wish you guys the best and hope my cynicism isn’t taken the wrong way here but reading between the lines… my sense is that there aren’t enough $NET or $FSLY customers asking for this and both companies aren’t interested in staffing a team to dedicate to GraphQL as a result but ARE willing to let you and your specialized team prototype it on their behalf. Not a bad dovetail. IMO if you get traction, you would be wise to take an early acquisition offer from Fastly or Cf. I was an early double digits engineer at Cloudflare and I can tell you, you REALLY don’t want to build a CDN to try to compete. Love them to death but look at ImgIX as a case study of how not to bizdev this same business model. Also, don’t entertain the idea that you can compete with a DIY VM-based “Cloud CDN”, it’s really not comparable. Look at the many dead “mobile first” CDN startups of 2014-2018, as case studies. Lastly, if you guys create a caching query planner on the edge, you might have a head start on a completely unmatched (afaik) product as an intelligent graphQL “gslb”. As a customer, if I can move my user data geographically closer to my users, that’s a big win for many reasons. Best of luck!
- the_mitsuhiko 5y agoHow does it deal with non yet propagated purges or are you always at risk of reading stale data for a short period?
- mxstbr 5y agoWe have plans to investigate adding global strong consistency in the future but we/Fastly don't currently support that! The purging takes ~150ms in the same datacenter that the mutation passes through, how long it takes globally depends on Fastly's bimodal multicast system — they've written a fascinating article about it that I'd highly recommend reading: https://www.fastly.com/blog/building-fast-and-reliable-purging-system https://www.fastly.com/blog/building-fast-and-reliable-purgi...
- hcentelles 5y agoI’ve being waiting for a product like this for some time now, I think there is a huge (not yet served) market for this. I’ve tried to implement something using Cloudflare workers, but failed, also tried to use Apollo Cloud trough a Apollo Federation server in front of my (non Apollo Server) API, failed too. Some questions: How it compares with Apollo Cloud on feature set terms? My graphql server load is like 20 request/s average. At first the pricing looks a little bit intimidating for me, but running the numbers it looks like $500/m, is that right? Hopefully it will offset some of my origin servers costs. What count as a request? Just request coming from the “outside” or also calls to purge for example? I’ll be trying GraphCDN soon, maybe even today. Good luck
- 0xy 5y agoApollo Cloud pricing is absurd at the enterprise level. I worked at two large companies who inquired and both balked. It was cheaper to build our own solution with plugins than it was to use their solution.
- timsuchanek 5y agoInteresting to know. For enterprises we even go down with the price per million requests, as the volume is much higher and therefore the enterprise pays enough already.
- timsuchanek 5y agoThanks @hcentelles, that's great to hear and gives us validation that there is a need! Compared to Apollo Cloud: We're mostly focused on the caching part right now and have a different architecture where we are in your stack. Apollo runs a sidecar next to your application. We are a proxy in front of your API. When it comes to the analytics part - which Apollo rather calls metrics, I think Apollo gives you field-level information, while we for now just have query-level information. However, we are fully server agnostic - you don't need to use Apollo Server. Any GraphQL API works. You just need to switch the URL in your clients. We even have customers just using the analytics part for now and disabling the caching in the beginning. For the pricing: That is correct - you'd have about 50mio requests a month, so $500. However, the pricing there is not set in stone and we're happy to give you an early discount. Just contact us at support@graphcdn.io. Right now only outside requests count as a request, no matter if cached or not. Purging calls might also count in the future.
- doteka 5y agoPardon me for asking a perhaps naive question, but how is this not a solution to a self-inflicted problem? Using a normal restful HTTP api has none of these issues. What is the big problem that GraphQL solves, and is it really serious enough to reinvent existing infrastructure for it?
- coffeedoughnuts 5y ago> Using a normal restful HTTP api has none of these issues I don't think a normal HTTP api provides anything to help with cache invalidation after a write operation, does it?
- timsuchanek 5y ago+1
- simplyinfinity 5y agohttps://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ET... Etags can be used to check and invalidate content.
- timsuchanek 5y agoYes, but as long as a cached version is still returned at the edge (while the real content might have changed), the ETag won't help. It can only save you from unnecessarily downloading content you already have - in case it didn't change.
- simplyinfinity 5y agoAnd when the content is updated you return different etag and the content is refreshed. Your system should have either distributed cache or a way for the edge to detect cache invalidations or for you to manually invalidate the cache on the edge.
- 5y ago
- deleted 5y ago[deleted]
- kenrose 5y agoTwo hard problems solved: 1. Cache invalidation 2. Decent project name Joking aside, this is great. Traditional CDNs + GraphQL always felt like an impedance mismatch.
- timsuchanek 5y agoThanks a lot kenrose! We promise to not dare tackling the 3rd big problem in computer science... 2 are enough for now. And indeed - current CDNs (as powerful and great as they are) are not at all equipped to deal with GraphQL.
- michaelmior 5y ago@mxstbr Looks cool! Small typo > our 58 data centers worlwide *worldwide
- timsuchanek 5y agoThanks Michael, we just fixed it! In a few min it'll be deployed.
- brotzky 5y agoThis looks really awesome. Congrats on shipping to the founders.
- blorenz 5y agoGraphCDN seemingly is an innovative service I'll be checking out, though I just wanted to comment that the app is a beautiful example of the use of Tailwind. I was a little taken aback because I was presuming styled-components but was delighted to see the well-executed use of one of my favorite libraries!
- timsuchanek 5y agoThanks blorenz! When working with Max, I was surprised how little he cared which library we use to get the job done. In fact, he's also a big fan of it. [0] To be fair, we use the Tailwind system, but a lot of customizations on top. [0] https://mxstbr.com/thoughts/tailwind/ https://mxstbr.com/thoughts/tailwind/
- HaD_XIII 5y agoCan't wait to see which additional use cases you'll add for GraphQL users in the future for additional peace of mind!
- nojvek 5y agoQ: Is the CDN cache consistent? i.e if I delete or change an object, does it immediately reflect across all the POPs across the globe? If so what are the potential read/write/latency speeds we can expect per object?
- nojvek 5y agoI've always felt that there should be a cloud hosted object database that should be query-able via graphql. It should offer auth and access rules like firebase. Really don't want to maintain a server. I love firebase for that reason, although querying it is a pain sometimes. Would love to make graphql queries so I can fetch multiple things in a single call.
- unraveller 5y agoDeepr looks promising https://github.com/deeprjs/deepr https://github.com/deeprjs/deepr you'd have to combine it with fauna for auth/RBAC etc the parallel "||" calls (push or pull) are great and the power to switch off a call you send with ? after the function name means all your calls during dev can be in a single text page and you just switch them on/off at will.