1"use strict";(self.webpackChunkpixelpoint_website=self.webpackChunkpixelpoint_website||[]).push([[9438],{6523:function(e,t,a){a.r(t),a.d(t,{Head:function(){return g},default:function(){return b}});var n=a(8453),s=a(6540);function r(e){const t=Object.assign({p:"p",h2:"h2",a:"a",span:"span",h3:"h3",img:"img"},(0,n.RP)(),e.components);return s.createElement(s.Fragment,null,s.createElement(t.p,null,"Real time updates are a part of almost every modern web and mobile application, with uses in everything from banking apps to news feeds. There are so many ways of handling real times updates that there will always be discussions about which way is better."),"\n",s.createElement(t.h2,{id:"a-bit-of-history"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#a-bit-of-history"},s.createElement(t.span,{className:"icon icon-link"})),"A bit of history"),"\n",s.createElement(t.p,null,"For the past 10 years, the most common approach was to use a websocket client, such as socket.io, and server and push events to the customers through it by triggering them inside your backend."),"\n",s.createElement(t.p,null,"There are also more recently developed data driven solutions, such as RethinkDB. I am a fan of this solution because, from my perspective, changes in the data should initiate events, clients should be subscribed for a specific query and data the clients should be changed accordingly. That what RethinkDB provides: good client libraries, their own query syntax, and scalability. Unfortunately, the RethinkDB project was closed and is now maintained only by the community."),"\n",s.createElement(t.p,null,s.createElement(t.a,{href:"https://graphql.org/"},"Graphql")," is another promising, more recent development, but early versions had no subscriptions at all so it remains to be seen how good it will be. GraphQL follows a similar approach to RethinkDB; it uses an effective, independent, and scalable solution where you can request data directly from the client, which is good for replacement of API calls to the backend."),"\n",s.createElement(t.p,null,"Currently, GraphQL can provide you realtime subscriptions, but the issue remains that GraphQL is a separate database. Itâs ok in many circumstances, but it isnât clear people can do if they use PostgreSQL. Not every company has the resources to initiate migration to GraphQL and, especially if you have a massive product, the large amount of logic on the DB level."),"\n",s.createElement(t.p,null,"We faced this issue with one of our own projects when we realised that we needed a simple way of implementing real-time updates without giving up PostgreSQL. This is where Hasura came in! I was so excited to find them at Product Hunt because Iâd wanted a solution for this problem for around three years."),"\n",s.createElement(t.h2,{id:"what-is-hasura"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#what-is-hasura"},s.createElement(t.span,{className:"icon icon-link"})),"What is Hasura?"),"\n",s.createElement(t.p,null,"Hasura is a proxy layer between your PostgreSQL database and Graphql server that allows you to set up real time updates very quickly from your PostgreSQL and itâs open-source. You get all the benefits of GraphQL without compromising access to your origin database, including client libraries for web and mobile, query syntax, and subscriptions."),"\n",s.createElement(t.h3,{id:"key-features-of-hasura"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#key-features-of-hasura"},s.createElement(t.span,{className:"icon icon-link"})),"Key features of Hasura"),"\n",s.createElement(t.p,null,"Real-time updates from your PostgreSQL database\nWhen I realized how easily this could be set up, it blew my mind."),"\n",s.createElement(t.img,{src:"/99df9571578f291b7fb9a5b25e195b49/real1.gif",alt:"GATSBY_EMPTY_ALT"}),"\n",s.createElement(t.h3,{id:"dynamic-access-control--auth"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#dynamic-access-control--auth"},s.createElement(t.span,{className:"icon icon-link"})),"Dynamic access control & auth"),"\n",s.createElement(t.p,null,"We use Auth0 with our projects; using Hasura, we were able to restrict access to the data while using JWT. Hasura also has a great, simple to use UX for c
1onfiguring access rules through the UI. Check out this video to see it in action."),"\n",s.createElement(t.p,null,"As an example, it is possible to have multiple tables that you use from the client part. You can configure it so that a user can only access the data if he is the owner of said data, and define whether that have read, write or delete permissions."),"\n",s.createElement(t.img,{src:"/796a4ad0ad340ba7b085439300d51446/real2.gif",alt:"GATSBY_EMPTY_ALT"}),"\n",s.createElement(t.h3,{id:"event-triggers-on-database-events"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#event-triggers-on-database-events"},s.createElement(t.span,{className:"icon icon-link"})),"Event triggers on database events"),"\n",s.createElement(t.p,null,"You could subscribe to each create, update, and delete action in your database and call another service by passing that data. A possible use case for that is as a communication channel between your microservices or to call serverless functions."),"\n",s.createElement(t.p,null,"The release of this feature was great; previously, we had used native PostgreSQL subscription to do this, but it required a lot of code to actually maintain it and there were no central point with a bulletproof solution."),"\n",s.createElement(t.p,null,"The really exciting thing is that itâs a highly reliable solution. No matter what happens with your Hasura or network connection, the event will be delivered once you bring it back. The same is true if, due to some unforeseen problem, the events changes came to PostgreSQL through API calls to the backend but another part of your application was down."),"\n",s.createElement(t.span,{dangerouslySetInnerHTML:{__html:'<span\n class="gatsby-resp-image-wrapper"\n style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 696px; "\n >
1\n <span\n class="gatsby-resp-image-background-image"\n style="padding-bottom: 84.48275862068965%; position: relative; bottom: 0; left: 0; background-image: url(\'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAARCAYAAADdRIy+AAAACXBIWXMAAAsTAAALEwEAmpwYAAABa0lEQVR42qVUy3LCMAz0/39Nv6bXXjoQjJP4GcuPjio5JJPCFAgcdghysl6vVhayH7A7Sfw+HHGChJDLWxD9MKIiGOcxpvw+oXMOjbUIKWEuZQXkhXzfJmI0lhQOqK27WUylbki3uEM4jBotkcUImDKrq+030H+tDYYpYqk/rc4AsiXe8Vq4ENpHiXZeyBjs50SkTLDU0kXtPa+Foi5L1bemcJd9jBhgVgvrkXd4aH0gMtfAz36aGlJ5sctSKZRnhZYIU5k9zLXu7u5KGOl47FWpM9HiI7yYSeHD1NQduw4Pxw6lPKOlKLVGbTxMT/opmKRjEmrK7GFsirlBW3CMnpkkMVLWOIvaGHTeX/JWGmlPgec1Hs9R61Z7ZIcwFGpHyrbhzZfjcYCbWsLq74OjCzXQNMR5jq8DHCiTTLoNPPwT+GVNJHCYM/y5GJbLgS0IlMnrOm90fZnMgojQfn1gUJ8IFdtLN5fDzmn5BUHrLtjHXRG/AAAAAElFTkSuQmCC\'); background-size: cover; display: block;"\n ></span>\n <picture>\n <source\n srcset="/static/f0f42d42845994502d3fa6e3369967b8/09400/real3.webp 174w,\n/static/f0f42d42845994502d3fa6e3369967b8/3266f/real3.webp 348w,\
1n/static/f0f42d42845994502d3fa6e3369967b8/657d2/real3.webp 696w,\n/static/f0f42d42845994502d3fa6e3369967b8/e644e/real3.webp 1044w,\n/static/f0f42d42845994502d3fa6e3369967b8/8daba/real3.webp 1392w,\n/static/f0f42d42845994502d3fa6e3369967b8/2deeb/real3.webp 1952w"\n sizes="(max-width: 696px) 100vw, 696px"\n type="image/webp"\n />\n <source\n srcset="/static/f0f42d42845994502d3fa6e3369967b8/88093/real3.png 174w,\n/static/f0f42d42845994502d3fa6e3369967b8/91d18/real3.png 348w,\n/static/f0f42d42845994502d3fa6e3369967b8/871fd/real3.png 696w,\n/static/f0f42d42845994502d3fa6e3369967b8/4e07d/real3.png 1044w,\n/static/f0f42d42845994502d3fa6e3369967b8/aeb15/real3.png 1392w,\n/static/f0f42d42845994502d3fa6e3369967b8/d9d67/real3.png 1952w"\n sizes="(max-width: 696px) 100vw, 696px"\n type="image/png"\n />\n <img\n class="gatsby-resp-image-image"\n src="/static/f0f42d42845994502d3fa6e3369967b8/871fd/real3.png"\n alt=""\n title=""\n loading="lazy"\n decoding="async"\n style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;"\n />\n </picture>\n </span>'}}),"\n",s.createElement(t.h3,{id:"ws-to-http-fallback"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#ws-to-http-fallback"},s.createElement(t.span,{className:"icon icon-link"})),"WS to HTTP fallback"),"\n",s.createElement(t.p,null,"Itâs not exactly related to Hasura, but when you use Graphql subscription when your client does not support WebSockets, it automatically uses HTTP as an alternative without any further actions from you."),"\n",s.createElement(t.p,null,"There are, of course, other features that you might find useful, such as mutation of your data and customer resolvers."),"\n",s.createElement(t.h2,{id:"personal-experience"},s.createElement(t.a,{"aria-hidden":"true",tabIndex:"-1",href:"#personal-experience"},s.createElement(t.span,{className:"icon icon-link"})),"Personal experience"),"\n",s.createElement(t.p,null,"Hasura is a really great product. Itâs been a huge time saver for us. It still doesnât have a stable release and is currently in development, but we already use it in production because all the features we use in our work operate without any problems. Almost every week, there is a new update the developers get closer to v1.0.0."),"\n",s.createElement(t.p,null,"Migration to a Hasura solution took just two weeks; one week of development by a single developer, and another week for bug fixes and QA. As a result, we got a good, sustainable solution we use for both the web and mobile apps. Our future plans with Hasura include using more event triggers and migration to serverless."),"\n",s.createElement(t.p,null,"You can immediately play around with Hasura for free through one click deployment to Heroku by following the link on their website If you would like to know more about that solution, Iâm happy to write another article explaining how to set it up on existing PostgreSQL and use it with your React/Redux application."))}var i=function(e){void 0===e&&(e={});const{wrapper:t}=Object.assign({},(0,n.RP)(),e.components);return t?s.createElement(t,e,s.createElement(r,e)):r(e)},o=a(2532),l=a(1021),c=a(545),u=a(9072),d=a(3669),h=a(9063),m=a(352),p=a(84);const f=e=>{let{data:{mdx:{author:t,frontmatter:a,fields:{slug:n}},allMdx:{nodes:r}},location:i,pageContext:{videoCovers:o},children:m}=e;return s.createElement(h.A,{headerTheme:"black",headerShowThemeButton:!0},s.createElement("article",{className:"safe-paddings pt-32 sm:pt-24"},s.createElement("div",{className:"container"},s.createElement("div",{className:"relative mx-auto max-w-[696px] xl:mx-0 xl:flex xl:max-w-none xl:justify-center xl:space-x-20 lg:space-x-8 md:block md:space-x-0"},s.createElement("div",{className:"xl:max-w-[696px] lg:max-w-[626px] md:max-w-none"},s.createElement(c.A,Object.assign({},a,{slug:n})),s.createElement(l.A,{content:m,videoCovers:o})),s.createElement(u.A,{author:t,readMorePosts:r,socialShareUrl:i.href})))),s.createElement(d.A,{withTopMargin:!0}))};function b(e){return s.createElement(f,e,s.createElement(i,e))}const g=e=>{let{data:{mdx:{frontmatter:{title:t,summary:a,ogImage:n}}}}=e;const r=(0,o.d)(n);return s.createElement(m.A,p.A.blogPost({title:t,description:a,ogImage:r}))}}}]); 2//# sourceMappingURL=component---src-templates-blog-post-jsx-content-file-path-content-posts-2018-11-15-real-time-postgres-index-md-0d0b083f03428a43891d.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.