<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Suhas Deshpande</title>
    <description>The latest articles on DEV Community by Suhas Deshpande (@suhasdeshpande).</description>
    <link>https://dev.to/suhasdeshpande</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F516348%2Fd05cfae2-d264-4282-9610-7e701a108d40.jpeg</url>
      <title>DEV Community: Suhas Deshpande</title>
      <link>https://dev.to/suhasdeshpande</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suhasdeshpande"/>
    <language>en</language>
    <item>
      <title>Building a Slack Integration for Your SaaS Notification System</title>
      <dc:creator>Suhas Deshpande</dc:creator>
      <pubDate>Thu, 04 Aug 2022 18:32:43 +0000</pubDate>
      <link>https://dev.to/courier/building-a-slack-integration-for-your-saas-notification-system-3lk8</link>
      <guid>https://dev.to/courier/building-a-slack-integration-for-your-saas-notification-system-3lk8</guid>
      <description>&lt;p&gt;For many organizations, Slack is the software of choice for business communication. Slack’s ubiquity in modern companies makes it one of the first notification integrations a SaaS company might want to build, possibly after email and mobile push notifications.&lt;/p&gt;

&lt;p&gt;In our experience, Slack notifications are a great way to reach business users (as Slack is mostly used in a business context) with time-sensitive alerts or action items while they’re at work. Because the users are already in work mode, Slack notifications are suitable for anything from collaboration on documents and spreadsheets to workflows like approval requests or data access permissions. Slack is less suited for notifications outside of a work context or out of working hours.&lt;/p&gt;

&lt;p&gt;To be able to send messages in Slack, a software system must integrate with &lt;a href="https://api.slack.com"&gt;Slack’s API&lt;/a&gt;. The resulting integration will allow your application to send Slack messages with helpful information to a Slack channel or a direct message thread. Here’s an example of a Slack message coming from &lt;a href="https://github.com/integrations/slack"&gt;GitHub’s Slack integration&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/z7iqk1q8njt4/20nZJwKjHk3HuFbsyPcANb/0fdc352178ee450eaab124d5b747c436/github-slack.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/z7iqk1q8njt4/20nZJwKjHk3HuFbsyPcANb/0fdc352178ee450eaab124d5b747c436/github-slack.png" alt="github-slack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s another example of a Slack integration from &lt;a href="https://help.salesforce.com/s/articleView?id=sf.digital_hq_slack_rn_approvals.htm&amp;amp;type=5"&gt;Salesforce&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="//images.ctfassets.net/z7iqk1q8njt4/1GKPrZsIjHdfb8u9mStEBt/7827b2be4ceb4b9325dafe8ac685c50b/salesforce-slack.png" class="article-body-image-wrapper"&gt;&lt;img src="//images.ctfassets.net/z7iqk1q8njt4/1GKPrZsIjHdfb8u9mStEBt/7827b2be4ceb4b9325dafe8ac685c50b/salesforce-slack.png" alt="salesforce-slack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many organizations don’t quite know what to expect when building an integration for sending messages from their SaaS product to a Slack channel or a direct message. In this post, we offer details for developers who are planning to build a Slack integration for their product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical aspects of a Slack integration
&lt;/h2&gt;

&lt;p&gt;From a technical perspective, Slack offers a fairly conventional HTTP REST API, which will be straightforward to understand for developers who deal with web systems. The functionality made available through the API is extensive, and there are complex parts to it, but most Slack integrations for SaaS will likely only need to send messages. Messages are the core of Slack’s functionality, but we cover other actions that your app might need to take in Slack below.&lt;/p&gt;

&lt;p&gt;For sending messages, the &lt;a href="https://api.slack.com/messaging/sending"&gt;Sending Messages guide&lt;/a&gt; in the Slack API documentation is a helpful starting point. The steps required to send a message are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a Slack app.&lt;/li&gt;
&lt;li&gt;Request the correct permissions from the user.&lt;/li&gt;
&lt;li&gt;Compose the message using one of Slack’s message types (or &lt;a href="https://api.slack.com/reference/block-kit/blocks"&gt;blocks&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Send the message via an API call.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The main way to send a message is the POST chat.postMessage endpoint, but it’s also possible to use other endpoints with slightly different functionality: the &lt;a href="https://api.slack.com/methods/chat.postEphemeral"&gt;chat.postEphemeral&lt;/a&gt; endpoint, for example, sends messages that are only visible temporarily and for a specific user (helpful for things like error messages). It’s also possible, and in some cases easier, to send messages using an &lt;a href="https://api.slack.com/messaging/webhooks"&gt;incoming webhook&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Beyond sending messages, other functionality that you can implement with Slack’s API includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Slash commands — simple chatbot functionality via commands in Slack DMs or channels&lt;/li&gt;
&lt;li&gt;Editing messages that have already been sent — for example, if information has been updated&lt;/li&gt;
&lt;li&gt;Bots that respond to direct mentions and interactions — for example, &lt;a href="https://slack.dev/hubot-slack/"&gt;Hubot&lt;/a&gt; is an implementation of such a bot used by hundreds of teams&lt;/li&gt;
&lt;li&gt;Bots that monitor all message traffic in a specific Slack channel or direct message thread (less common due to how inefficient it is to scan all messages in high-volume Slack channels)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many software teams choose to develop all functionality relating to Slack or another messaging service either in a dedicated microservice (if you use microservice architecture) or at least in a separate section of your monolithic app. The reason to do this is to avoid tightly coupling the way you think about notifications to Slack’s API — doing so could cause issues when the time comes to add support for other messaging APIs. Another reason to use a separate service or namespace for the Slack integration is to implement message retries and other reliability-focused tweaks. Such code would be too complex to include inside your business logic.&lt;/p&gt;

&lt;p&gt;In our experience, there are a few points that developers might not be thinking about when building a Slack integration, and we encourage you to consider them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Many of our users run into Slack API rate limits at some point during their usage cycle. So it’s likely that you will need to retry sending a message at some point because of rate limits. Consider including retry functionality from the very beginning.&lt;/li&gt;
&lt;li&gt;Messages sent by integrations might need to include images or other files, so consider how you’ll handle attachments. Slack offers convenient &lt;a href="https://api.slack.com/methods/files.upload"&gt;file upload&lt;/a&gt; functionality via the API that you can use, and it comes with built-in access controls. But you might prefer to &lt;a href="https://api.slack.com/messaging/files/remote"&gt;use your own storage&lt;/a&gt;. In that case, authenticating requests to files can become painful because you won’t have Slack’s access control mechanism to rely on.&lt;/li&gt;
&lt;li&gt;Make sure that your system is compliant with relevant regulations, in case you’re sending notifications that include PII or other sensitive data. We wrote about this recently in &lt;em&gt;&lt;a href="https://www.courier.com/blog/the-developers-guide-to-saas-compliance/"&gt;The Developer's Guide to SaaS Compliance&lt;/a&gt;&lt;/em&gt; — check it out. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  User experience of a Slack integration: Our recommendations
&lt;/h2&gt;

&lt;p&gt;When we advise our customers about Slack integrations, most of our advice centers less on the implementation details and more on the product functionality and customer experience side. We see teams who are building Slack notification functionality for their SaaS focus too much on sending Slack messages and not enough on the value those notifications deliver to their users.&lt;/p&gt;

&lt;p&gt;In this section, we offer a few recommendations on designing a helpful Slack notification experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Slack status information for optimal notification experience
&lt;/h3&gt;

&lt;p&gt;Something that we find useful for many customers is keeping track of Slack statuses (the little “active” and ”away” indicators you see on people’s profiles). Consider whether you even want to send Slack notifications if someone is marked as being away in Slack — they might not be on their computer, or they might have intentionally changed their status. Is the notification you’re sending in Slack going to be actionable for someone on their phone? For many SaaS applications, the answer is no.&lt;/p&gt;

&lt;p&gt;Our recommendation on handling status is to send Slack notifications when the user is active in Slack, and when they are not active, using a different channel like email or mobile push.  We cover the topic of notification routing in &lt;em&gt;&lt;a href="https://www.courier.com/blog/routing-and-preferences/"&gt;Building a Routing and Preferences Service for Notifications&lt;/a&gt;&lt;/em&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Create message templates and have a workflow for updating them
&lt;/h3&gt;

&lt;p&gt;In a SaaS product, it’s very unlikely that you’ll need just one type of Slack message. An app can require tens or hundreds of different notifications to be sent via Slack — and managing such large numbers of messages in your codebase can get tricky.&lt;/p&gt;

&lt;p&gt;We recommend using templates instead of hard-coding messages in your application. It’s likely that your message templates will change over time, and you might want to add new notification types as you develop your product. By relying more on templates you can simplify the code review process — it’s easier for a peer to review a template change in a separate file than to jump between templates and code.&lt;/p&gt;

&lt;p&gt;Another recommendation is to make templates editable outside of the code review process. This capability will enable colleagues outside of the development team to change and tweak notification templates themselves without the need to commit directly to the codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Translation and language preferences
&lt;/h3&gt;

&lt;p&gt;Are you going to only offer notifications in one language, or multiple? If you’re offering multiple languages, how does a user configure their preferences? You might want to add functionality within the Slack app that allows users to configure their language settings, or have a section within your web app (outside of Slack) with notification preferences. In any case, you need to store language preferences for each user and, eventually, have a good way to store translated versions of notification text as well.&lt;/p&gt;

&lt;p&gt;We also recommend that you consider the translation workflow for notification text — the translators will likely not be able to navigate your codebase due to limited permissions or lack of technical context. Making it straightforward for the translators to work with your notification text will make it faster to implement new notification languages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Slack integrations made easier with Courier
&lt;/h2&gt;

&lt;p&gt;In this article, we’ve covered our recommendations for building a successful Slack integration for your SaaS product.&lt;/p&gt;

&lt;p&gt;Prefer not to implement the integration yourself?&lt;/p&gt;

&lt;p&gt;With Courier, sending a Slack message only requires one API call to Courier’s &lt;a href="https://www.courier.com/docs/guides/providers/direct-message/slack/#send-a-message"&gt;send&lt;/a&gt; endpoint. As part of that endpoint, Courier uses &lt;a href="https://www.courier.com/docs/reference/profiles/"&gt;profile information&lt;/a&gt; to customize notifications, from individual preferences and personal information to language settings. Courier also offers &lt;a href="https://www.courier.com/features/templates/"&gt;templates&lt;/a&gt; that can be created in a well-designed web user interface (with a translation workflow built-in) and &lt;a href="https://www.courier.com/features/automations/"&gt;automations&lt;/a&gt; to define more advanced notification logic. And, by the way, once you integrate Courier, you can send other message types — like Microsoft Teams, Discord, email, SMS, and more.&lt;/p&gt;

&lt;p&gt;If you’re interested in offloading building a strong Slack integration for your SaaS notification system, &lt;a href="https://app.courier.com/signup"&gt;explore Courier&lt;/a&gt; and see if buying might be a better option than building in this case!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Illustration by &lt;a href="https://www.rrebekkaa.com/"&gt;Rebekka Dunlap&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>slack</category>
      <category>saas</category>
      <category>integration</category>
      <category>notification</category>
    </item>
    <item>
      <title>How I Used Raspberry Pi to Detect Water Leaks in My Home</title>
      <dc:creator>Suhas Deshpande</dc:creator>
      <pubDate>Thu, 21 Apr 2022 17:44:33 +0000</pubDate>
      <link>https://dev.to/courier/how-i-used-raspberry-pi-to-detect-water-leaks-in-my-home-254j</link>
      <guid>https://dev.to/courier/how-i-used-raspberry-pi-to-detect-water-leaks-in-my-home-254j</guid>
      <description>&lt;p&gt;When I realized there was a leak in my home, I knew it was time to put my expertise to work. I needed to call on my years of experience and passion for my job - as a software engineer? While at first glance, it may appear that a plumber would have been a better option, my argument is that there is a step to be taken before a plumber is even involved to fix a leak. And that is to detect the leak when it first happens. &lt;/p&gt;

&lt;p&gt;Sure, I could have a plumber on call who checks for leaks every day, but seeing as that’s not an effective use of time or money, we needed to find an alternative to waiting for the problem to become bad enough to become a major problem. So if a 24/7 plumber-butler wasn’t an option, I thought some kind of automated system would be more realistic.&lt;/p&gt;

&lt;p&gt;As it turns out, I had been thinking for some time about how to use a Raspberry Pi with Courier to bring notifications to life. This happened to be a perfect use case to try it out, so I decided to invest in the appropriate hardware and make use of my own software development skills to make sure that I would get a notification any time there was even a small leak in my home. This way, I’d know to call the plumber and handle the problem before it became too big to handle.&lt;/p&gt;

&lt;h2&gt;
  
  
  A leak can become an expensive problem
&lt;/h2&gt;

&lt;p&gt;I myself had a water leak in my apartment some time ago. Because I didn’t know there was a problem until it was already too late, I had to call for a plumber when the damage was already done. Even for a simple leak like this, I ended up spending more than $500 to fix it. &lt;/p&gt;

&lt;p&gt;But things could have been much worse. Major damage is often caused by mold spores.&lt;br&gt;
Water leaks may also cause structural damage to property. Walls start swelling and warping, leading to cracks and holes in them. Furthermore, water leaks may negatively impact the value of a home.&lt;/p&gt;

&lt;p&gt;I never wanted to deal with the complications, so I decided to take matters into my own hands. But of course, it was important to find a solution that would be fun and interesting as well as useful. &lt;/p&gt;

&lt;h2&gt;
  
  
  Building alerts for water leaks using Raspberry Pi
&lt;/h2&gt;

&lt;p&gt;During my research for a solution in the form of alerts for water leaks, I found that I could use a small, affordable &lt;a href="https://www.raspberrypi.com/"&gt;Raspberry Pi&lt;/a&gt; single-board computer to achieve my goal. With this tiny computer, I could read signals from my water sensor and then send those signals to my monitor. &lt;/p&gt;

&lt;p&gt;To develop the project, which I called &lt;a href="https://github.com/suhasdeshpande/potential-octo-lamp"&gt;potential-octo-lamp&lt;/a&gt;, I first got all the hardware I needed to detect water leaks and connect to my computer. These devices included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/dp/B07WYC73LF?psc=1&amp;amp;ref=ppx_yo2_dt_b_product_details"&gt;Raspberry Pi 4 Model B&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/dp/B079YB1T8J?psc=1&amp;amp;ref=ppx_yo2_dt_b_product_details"&gt;Floor Water Sensor for Flood and Leak Detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/dp/B08GYKNCCP?psc=1&amp;amp;ref=ppx_yo2_dt_b_product_details"&gt;SanDisk 128GB Ultra MicroSDXC UHS-I Memory Card with Adapter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/dp/B08736NSPK?psc=1&amp;amp;ref=ppx_yo2_dt_b_product_details"&gt;GPIO Breakout Expansion Kit for Raspberry Pi 4B&lt;/a&gt;
The next step was to build “potential-octo-lamp” to send alerts for any detected water leaks. I built the project to check for leaks from the sensor using JavaScript and TypeScript programming languages. When potential-octo-lamp detects one, it then sends the result to my phone using Courier and Twilio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With &lt;a href="https://www.courier.com/"&gt;Courier&lt;/a&gt;, I could create custom alerts and define their titles and body text. I could also specify the communication channels through which the alerts should go and the recipients of these alerts. I also added a &lt;a href="https://www.twilio.com/"&gt;Twilio&lt;/a&gt; integration on Courier to deliver the contents of my alerts through the channels I specified — in this case, SMS and email.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use potential-octo-lamp to get alerts
&lt;/h2&gt;

&lt;p&gt;Luckily, I’m a really nice guy and have made potential-octo-lamp open source. You can use my program to protect your own home from water leaks. Once you have all the hardware requirements listed above, connect your Raspberry to your water sensor. If you need help setting them up, this &lt;a href="https://www.youtube.com/watch?v=KwKiiWYQies"&gt;tutorial&lt;/a&gt; will help. Then you can begin using potential-octo-lamp to receive alerts for water leaks in five easy steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create Your Courier and Twilio Accounts
&lt;/h3&gt;

&lt;p&gt;If you don’t already have &lt;a href="https://app.courier.com/register"&gt;Courier&lt;/a&gt; and &lt;br&gt;
&lt;a href="https://www.twilio.com/try-twilio"&gt;Twilio&lt;/a&gt; accounts, you’ll need to sign up for both to configure your alert system. You may sign up for free on Courier and Twilio using an email address. Courier also allows you to use your Google or GitHub account to create an account.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Add Your Twilio Integration in Courier
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.courier.com/docs/guides/providers/sms/twilio/"&gt;Start by getting&lt;/a&gt; your Account SID, Auth Token, and messaging service SID from Twilio. Then log into your Courier account and go to &lt;a href="https://app.courier.com/integrations"&gt;Integrations&lt;/a&gt;. Add the Twilio info to their corresponding fields in Courier.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Retrieve Your Courier Authorization Token
&lt;/h3&gt;

&lt;p&gt;When you create an account with Courier, you get an Auth Token so that you can safely make requests to and from Courier. Once logged in, you may retrieve your Courier Auth Token from the &lt;a href="https://app.courier.com/settings/api-keys"&gt;API keys page in Settings&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Clone potential-octo-lamp and Add Your Courier Auth Token
&lt;/h3&gt;

&lt;p&gt;Next, go to GitHub and clone &lt;a href="https://github.com/suhasdeshpande/potential-octo-lamp"&gt;potential-octo-lamp&lt;/a&gt;. Because it’s unsafe to input your Courier Auth Token directly in your code, create a .env file and add it there. That way, it’s only visible to you.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Start the App
&lt;/h3&gt;

&lt;p&gt;Finally, run the following commands one after the other to install dependencies and start checking for water leaks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;npm install&lt;/p&gt;

&lt;p&gt;npm run build&lt;/p&gt;

&lt;p&gt;npm run start&lt;/p&gt;
&lt;/blockquote&gt;


&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://www.loom.com/embed/6c977bc087fd4943b27fbda8c2069f65"&gt;Loom Video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As soon as your floor water sensor detects leaks, potential-octo-lamp sends alerts for water leaks to the recipients you added on Courier. Then you can quickly repair the leak to prevent further damage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alerts are your answer to urgent situations
&lt;/h2&gt;

&lt;p&gt;Potential-octo-lamp is open-source, so you can clone it and use it yourself. Any improvements or suggestions you may have are also welcome. You can raise an issue or &lt;a href="https://www.linkedin.com/in/suhasrdeshpande/"&gt;reach out&lt;/a&gt; to me if you’d like to contribute to the project!&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why You Can't Replace REST with GraphQL</title>
      <dc:creator>Suhas Deshpande</dc:creator>
      <pubDate>Fri, 09 Jul 2021 18:49:25 +0000</pubDate>
      <link>https://dev.to/courier/why-you-can-t-replace-rest-with-graphql-2fik</link>
      <guid>https://dev.to/courier/why-you-can-t-replace-rest-with-graphql-2fik</guid>
      <description>&lt;p&gt;When I Googled “what is GraphQL” to learn more about the network protocols, all I saw was a comparison between REST and GraphQL. Most of the conclusions said, “use GraphQL.” It felt very binary (and trendy, for that matter), which is a problem because each product and use-case is unique. The fact is, whatever is newest and shiniest gets recommended more loudly. But you have to weigh the trade-offs and come up with a solution that is best for your situation. &lt;/p&gt;

&lt;p&gt;There is a general understanding that either REST is better than GraphQL or vice versa. But the truth is they both address different problems and have different strengths and weaknesses. The question isn’t necessarily which one is better to use, but which one is better to use for specific circumstances. The best way to evaluate GraphQL, REST, or any other technology is to figure out your constraints based on the problem you are going to solve.&lt;/p&gt;

&lt;p&gt;REST is a familiar option that can be implemented quickly&lt;br&gt;
REST is the popular option, and for good reason: it’s quick to learn and implement. No one wants to write complex code if they don’t have to, so it’s not hard to see why quick and easy REST beats complex and clever GraphQL in most situations.&lt;/p&gt;

&lt;p&gt;Two aspects of REST really shine. The first is that most ORMs (object–relational mapping) are optimized to work with REST, so that is not a problem you will have to solve. The second is REST is ideal for quick transactional requests, like the following:&lt;/p&gt;

&lt;p&gt;Hey Courier, here is the payload (data), and I want to send a notification.&lt;/p&gt;

&lt;p&gt;Hey Courier, what is the status of the last message I sent? Here is the ID since you don’t remember anything (stateless protocol so every request would provide precise input to query the state).&lt;/p&gt;

&lt;p&gt;Additionally, with REST, you share the complexity between client and server. It has the benefit of proven patterns on how to do something, and it is definitely a well-proven, time-tested way of writing applications.&lt;/p&gt;

&lt;p&gt;GraphQL is a different approach entirely, and it takes time and effort to create harmony. A system that is ideal for all your use cases will demand a lot of your time and will require your team to learn a lot of new concepts. It will force you to think in a certain way. We knew the cost of implementing GraphQL was probably going to be exhaustive — we expected the move was not going to be a do-it-once-and-forget-it thing.&lt;/p&gt;

&lt;p&gt;The default option would be REST, and it’s a good one. Not just because it’s easy, but because there is an expectation of shared familiarity. Developers are likely to already know REST, whereas the same is not true for GraphQL. Unless you’ve identified needs that GraphQL is especially good at solving, REST is the default choice for a good reason. We would rather rest easy with REST, build something that both excites and helps our users, and get their product in the hands of their friends and family with time-tested methods.&lt;/p&gt;
&lt;h2&gt;
  
  
  REST vs. GraphQL
&lt;/h2&gt;

&lt;p&gt;Let’s get right into it. With REST, there’s a lot of back and forth and manual work. Calls can result in either over-fetching or under-fetching based on the API contract. For example, if you end up with URIs (uniform resource identifiers) and not the specific data you’re looking for, the network calls you need to make on your client to get what you need escalate quickly.&lt;/p&gt;

&lt;p&gt;Whereas GraphQL gets exactly the data you want on an API call. You have control over the query on a granular level, which is not something you can not easily do with REST since it’s not made for that specific purpose. Having this granular control will allow you to have fewer network calls and will require fewer developmental changes on client applications, since responsibility has been shifted to backends.&lt;/p&gt;

&lt;p&gt;Applications can be informationally and visually heavy and also need to retrieve a variety of interconnected data. Fewer network calls in this scenario can be crucial for performance when this data needs to be retrieved in what are potentially many different and unknown situations. With the right implementation of GraphQL, you can eliminate the ability to over-fetch.&lt;/p&gt;

&lt;p&gt;If your application is reading 1MB of data locally, it can finish the job in 0.4 milliseconds — as opposed to reading it over the network, which can take 150 milliseconds — a drastic difference. The point here is you want to optimize for fewer network requests. REST doesn’t give you those affordances. If optimizing for network requests is the most important factor, GraphQL would work better for you.&lt;/p&gt;

&lt;p&gt;With GraphQL, you’ll get only the information you need. This is due to a self-documenting schema that’s easier to consume and has better tooling around consuming your endpoint.&lt;/p&gt;
&lt;h2&gt;
  
  
  GraphQL is more than just making queries
&lt;/h2&gt;

&lt;p&gt;Writing GraphQL queries is just the tip of the iceberg. Implementing a brand new solution with GraphQL comes with challenges to overcome and problems to solve. The GraphQL stack might appear to be simple to get started with, but it gets complex quickly. It requires a lot of upfront learning and can be intimidating for newcomers to figure out how all these pieces fit together. Before you move to GraphQL, you need to understand what you’re signing up for.&lt;/p&gt;

&lt;p&gt;Since GraphQL is not built into an ORM, it means there’s a lot of architectural choices that need to be made for your stack that will require extra effort to set up. It also comes with a steep learning curve. Part of that learning curve is control. GraphQL inverts control and hands it over to the client. Any amount of information can be requested, which means building a third-party API can become burdensome if you have expensive queries.&lt;/p&gt;

&lt;p&gt;We all know naming things is hard, and GraphQL makes this a little harder. The GraphQL schema is a list of object types. It’s more than just a catalog; it’s a snapshot of the API. In a very large codebase, this could lead to naming collisions, so thoughtful naming conventions are a must.&lt;/p&gt;

&lt;p&gt;In addition to the learning curves we’ve found ourselves dealing with, caching, one of the most loved and hated topics in computer science, is a whole lot more adventurous with GraphQL. Caching can happen on the client or on the server. REST uses headers to control the caching. However, GraphQL doesn’t have this affordance at the HTTP level.&lt;/p&gt;

&lt;p&gt;All POST requests in GraphQL automatically opted out of the free HTTP caching you get in the browser. That means you have to bring your own cache when you’re in GraphQL land. Not only is this caching solution something you have to build, but you also have to maintain it — a consideration that should be thought about thoroughly.&lt;/p&gt;

&lt;p&gt;In the end, you want to build something useful. GraphQL and REST can get you there, but be mindful about what either option means for you and your team long term. We identified that GraphQL was a great solution for some of our needs.&lt;/p&gt;
&lt;h2&gt;
  
  
  The REST and GraphQL partnership
&lt;/h2&gt;

&lt;p&gt;The general wisdom is to choose either REST or GraphQL for your needs, but in reality, neither one covers all the bases. Our biggest motivation when building something is to evaluate how a developer would like using it. We started gradually introducing GraphQL first in our own internal APIs. We converted those endpoints to see how they worked for us internally before we exposed them externally.&lt;/p&gt;

&lt;p&gt;But for Courier’s studio application, we went with GraphQL. Even though REST would allow us to build it, it wasn’t necessarily the best solution. It would require us to either implement (or add more) logic to handle new information and endpoints every time we decide to have new info on a page. Because the application has a growing need for data and information, and GraphQL solves this problem better for us.&lt;/p&gt;

&lt;p&gt;Our backend data objects and business objects are rapidly becoming more interconnected, and GraphQL is a good way to relate each business object within our ecosystem. Managing all that in REST would be quite a task. And it comes with the downside of additional network requests.&lt;/p&gt;

&lt;p&gt;GraphQL solved our constraints fairly well. So while conventional wisdom states we should move to GraphQL entirely, the fact is, for customer-facing APIs, we need REST. For our own frontends, however, GraphQL is the answer.&lt;/p&gt;
&lt;h2&gt;
  
  
  The GraphQL journey at Courier
&lt;/h2&gt;

&lt;p&gt;We decided to tackle the learning curve even though learning has uncertain pay-offs. Everything we do has opportunity cost, and early adoption of something like GraphQL can feel like &lt;a href="https://en.wikipedia.org/wiki/Cargo_cult_programming"&gt;cargo cult-like&lt;/a&gt; behavior. But in the end, GraphQL works for us, with our circumstances.&lt;/p&gt;

&lt;p&gt;Courier frontend is growing rapidly with the need to present rich information coming from various sources. REST could work, but GraphQL would work even better because of the query-able, type-safe nature of GraphQL.&lt;/p&gt;

&lt;p&gt;Let’s take a look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Notification&lt;/span&gt; &lt;span class="kr"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nl"&gt;archived&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;
   &lt;span class="nx"&gt;brandEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;
   &lt;span class="nx"&gt;brandId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
   &lt;span class="nx"&gt;categoryId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
   &lt;span class="nx"&gt;created&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;iso8601&lt;/span&gt;
   &lt;span class="nx"&gt;draftId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;
   &lt;span class="nx"&gt;draft&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TemplateDraft&lt;/span&gt;
   &lt;span class="nx"&gt;eventMaps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventMapConnection&lt;/span&gt;
   &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
   &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
   &lt;span class="nx"&gt;tagIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="nx"&gt;templateId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
   &lt;span class="nx"&gt;updated&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;iso8601&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a type defined in our GraphQL. We know in the future this Notification node will have more information needed. Say, a use-case to present all the collaborators involved in building this notification. With GraphQL (based on our existing pattern), we can easily extend the Notification node and add an edge or connect it to User (collaborator), so this extensibility works out great for our use case.&lt;/p&gt;

&lt;p&gt;Another big advantage of GraphQL is the fact we can choose what data to get from our backend. Let’s steal this analogy from &lt;a href="https://overreacted.io/"&gt;Dan Abramov&lt;/a&gt; where he explains the new React 18 &lt;a href="https://github.com/reactwg/react-18/discussions/21"&gt;batch rendering&lt;/a&gt; feature. Let’s say you need to go shopping for breakfast items at the store. Not only would you ideally like to come up with a reasonable list of items before going to the store, but you’d also want to optimize the number of trips you need to take.&lt;/p&gt;

&lt;p&gt;The grocery scenario is quite similar to client applications needing to make additional network calls to the backend, like every time there’s a need for additional fields. GraphQL solves this by providing a declarative, type-safe mechanism to query data from your backend.&lt;/p&gt;

&lt;p&gt;It’s fairly easy to look at the query below and figure out what information you can get.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
           &lt;span class="nx"&gt;label&lt;/span&gt;
           &lt;span class="nx"&gt;key&lt;/span&gt;
       &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;signature&lt;/span&gt;
           &lt;span class="nx"&gt;workspace&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="nx"&gt;created&lt;/span&gt;
               &lt;span class="nx"&gt;id&lt;/span&gt;
               &lt;span class="nx"&gt;name&lt;/span&gt;
               &lt;span class="nx"&gt;usage&lt;/span&gt;
           &lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="nx"&gt;userId&lt;/span&gt;
       &lt;span class="nx"&gt;firstName&lt;/span&gt;
       &lt;span class="nx"&gt;lastActive&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And tooling like &lt;a href="https://graphql.org/learn/introspection/"&gt;introspection&lt;/a&gt; allows us to go even further! Introspection lets you gather information about supported queries in the GraphQL schema — you can get autocomplete schema definitions with type information. Beyond that, strong-typing makes introspection easier. This can be accomplished using TypeScript interfaces and is what will allow you to specify what your data is as well as automate a lot of the documentation.&lt;/p&gt;

&lt;p&gt;This declarative approach to query information resonated with us about why GraphQL is compelling to use. So we chose GraphQL for our client applications because it provides strong typing and structured queries. GraphQL has a specification that makes it intuitive to build applications.&lt;/p&gt;

&lt;p&gt;We haven’t given up REST altogether, though — we’re still using REST for our external APIs. This is because they’re transactional in nature, and it isn’t advantageous for us to expose an external GraphQL endpoint just yet based on the &lt;a href="https://docs.courier.com/reference/introduction"&gt;simplicity of our REST endpoints&lt;/a&gt;.&lt;br&gt;
These are some of the reasons we love GraphQL at Courier.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we’ve learned
&lt;/h2&gt;

&lt;p&gt;Since we are a developer API product, it’s expected that we support all formats, REST obviously included. REST is widely used, popular, easy to maintain, and has an easy triage way of exposing endpoints. We know how and what to measure in our REST endpoints. We have pretty decent tooling built around the REST ecosystem, and moving it to GraphQL won’t add much value to the user or the business right away.&lt;/p&gt;

&lt;p&gt;But GraphQL works best for us moving forward with our client applications. Exposing Courier’s functionality to external developers, we will still be resting on REST. And we still have a decent amount (if not most) of Courier’s functionality exposed via REST endpoints.&lt;/p&gt;

&lt;p&gt;We have been running GraphQL on NodeJS for more than one year at this point. It has increased our velocity to push new features as well as given us a significant performance boost in our Studio application. We get the advantage of the high bandwidth on the server side to pull data from GraphQL’s middle layer, which is responsible for stitching data from various data sources.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what’s right for you?
&lt;/h2&gt;

&lt;p&gt;GraphQL is an exciting field — with a learning curve! But once you get the hang of it, specifications provide great tooling out of the box and saves a lot of code. Finding the balance between getting features out the door and adopting new technology can be a challenge. Finding the iterative approach that gives you time to adopt new technology would help you gradually increase your chances of success.&lt;/p&gt;

&lt;p&gt;So there is no silver bullet that solves all the problems. New solutions are inspired by shortcomings in existing technology, but they come with new sets of challenges. Everyone’s situation is different, and contextualizing the solutions based on your problem space is the way to think when making these fun decisions.&lt;/p&gt;

</description>
      <category>rest</category>
      <category>graphql</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
