<?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>Forem: Nikolaj Dyring</title>
    <description>The latest articles on Forem by Nikolaj Dyring (@nikodyring).</description>
    <link>https://forem.com/nikodyring</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%2F505516%2F51db51dc-4821-4f61-ac24-2a54c82e7021.jpeg</url>
      <title>Forem: Nikolaj Dyring</title>
      <link>https://forem.com/nikodyring</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/nikodyring"/>
    <language>en</language>
    <item>
      <title>The Pragmatic Programmer: Lessons That Still Matter</title>
      <dc:creator>Nikolaj Dyring</dc:creator>
      <pubDate>Fri, 14 Nov 2025 22:51:21 +0000</pubDate>
      <link>https://forem.com/nikodyring/the-pragmatic-programmer-lessons-that-still-matter-51ml</link>
      <guid>https://forem.com/nikodyring/the-pragmatic-programmer-lessons-that-still-matter-51ml</guid>
      <description>&lt;p&gt;NOTE: I'd love to do better formatting. But for some reason I can't do line breaks in-between list items.&lt;/p&gt;

&lt;p&gt;For over two decades, &lt;em&gt;The Pragmatic Programmer&lt;/em&gt; has influenced how developers think about their craft, responsibility, and long-term software quality. The 20th Anniversary Edition gives the classic a modern polish while keeping its core philosophy intact. &lt;/p&gt;

&lt;p&gt;After reading it, I've decided to put down some of the core lessons, and how I've interpreted them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Lesson 🧠
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Care About Your Craft&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;If you're going to write software, aim to write it well. Quality isn't a luxury; it's the compound interest of good habits.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Don't Live with Broken Windows&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Small flaws invite bigger ones. Fix issues as soon as you see them. Sloppy logic, poor naming, outdated comments, or brittle tests.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Invest in Your Knowledge Portfolio&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Treat learning like long-term investing. Learn new languages, explore new paradigms, follow trends, and revisit fundamentals regularly.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;English Is Just Another Programming Language&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Communication is part of the job. Well-structured documentation, clear naming and concise explanations prevent misalignment and reduce friction.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Good Design Is Easy To Change&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;If it's painful to modify, it's not good design. Lean on modularity, loose coupling, and clean boundaries to make future changes compatible.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DRY - Don't Repeat Yourself&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;One truth. One place. Duplication breeds divergence. Consolidate logic so it stays reliable and predictable.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prototype to Learn&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;When you're unsure, build something small. Prototyping clarifies requirements, exposes pitfalls, and prevents wasted time.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refactor Often&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Think of refactoring like tending a garden. Regular small cleanups keeps your software healthy and prevent large-scale rewrites.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Take Small, Reversible Steps&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;Break big work into tiny experiments. Ship incrementally, gather feedback, adjust quickly.&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Take ✋
&lt;/h2&gt;

&lt;p&gt;Reading the updated edition today reinforces how timeless most of its guidance is. The fundamentals; ownership, clarity, continuous learning and adaptability still matter more than any specific framework or trend.&lt;/p&gt;

&lt;p&gt;Some older examples were revised or replaced, making the book feel current without losing its roots. A few ideas are so commonplace now (like "remember to use version control") that they feel obvious, but the broader mindset still hits home.&lt;/p&gt;

&lt;p&gt;Compared to other books I've recently read like Clean Code or Code Complete, this one is less about strict technique and more about how to think as a software developer. That's why it continues to resonate. It's a philosophy as much as a manual.&lt;/p&gt;

</description>
      <category>softwaredevelopment</category>
      <category>books</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>gRPC vs REST</title>
      <dc:creator>Nikolaj Dyring</dc:creator>
      <pubDate>Thu, 30 Oct 2025 08:12:17 +0000</pubDate>
      <link>https://forem.com/nikodyring/grpc-vs-rest-1jh9</link>
      <guid>https://forem.com/nikodyring/grpc-vs-rest-1jh9</guid>
      <description>&lt;p&gt;TL;DR:&lt;br&gt;
We benchmarked REST vs gRPC under identical local setups using .NET. While gRPC is widely believed to outperform REST, our results show REST can be equally, or even slightly faster in specific data-heavy operations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;As microservices multiply across modern systems, the choice of API protocol can make or break performance. REST has ruled for years, but gRPC promises to be faster, leaner and more efficient. So why hasn't it taken over? Microservices can be heavily dependent on each other, which means speed and stability is key. When gRPC claims to be faster than REST, why isn't it the de facto standard? In this blog we will put gRPC and REST head to head, to see which is actually faster.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;gRPC is a superior technology to REST!&lt;/strong&gt; At least that is what &lt;a href="https://code.tutsplus.com/tutorials/rest-vs-grpc-battle-of-the-apis--cms-30711" rel="noopener noreferrer"&gt;this&lt;/a&gt;&lt;code&gt;1&lt;/code&gt;, &lt;a href="https://medium.com/@bimeshde/grpc-vs-rest-performance-simplified-fd35d01bbd4" rel="noopener noreferrer"&gt;this&lt;/a&gt;&lt;code&gt;2&lt;/code&gt;, &lt;a href="https://www.yonego.com/nl/why-milliseconds-matter/#gref" rel="noopener noreferrer"&gt;this&lt;/a&gt;&lt;code&gt;3&lt;/code&gt; and &lt;a href="https://medium.com/@EmperorRXF/evaluating-performance-of-rest-vs-grpc-1b8bdf0b22da" rel="noopener noreferrer"&gt;this blog&lt;/a&gt;&lt;code&gt;4&lt;/code&gt; claims. According to all the mentioned blogs, gRPC performs better and faster than a REST on several metrics. In this blog we will test specifically, how &lt;strong&gt;&lt;em&gt;fast&lt;/em&gt;&lt;/strong&gt; a REST client can handle different request and responses, and compare it to how fast a similar gRPC client handles the same requests and responses. This begs the question...&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Is gRPC faster than REST?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We hypothesize that gRPC is able to send and receive requests faster than a traditional REST.&lt;/em&gt; To test this, the following experiments have been developed.&lt;/p&gt;
&lt;h2&gt;
  
  
  The experiment
&lt;/h2&gt;

&lt;p&gt;To test the Hypothesis two experiments, one utilizing gRPC and one utilizing REST. These experiments have to adhere to the following:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rules&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To ensure accurate measurements, the results must be obtained from the same computer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multiple data structures will be tested.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The setup for both APIs has to be as similar as possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The time used for measuring should be obtained from the client.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Set up&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To adhere to the multiple data structures rule, a local database has been created, this database will provide a single instance of an object, as well as multiple instances of objects that will be stored in a list.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each API will have 12 methods to call.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Three for a single instance which takes a parameter of Id.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each one with a larger payload&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Three for a single instance which takes a parameter of Id.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each one with a deeper payload&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Three for a collection of 100 instances, which takes no parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each one with a larger payload&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Three for a collection of 100 instances, which takes no parameters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each one with a deeper payload&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each API will be tested with a client written in C#, as a console app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time will be measured with &lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.8" rel="noopener noreferrer"&gt;.NET Stopwatch&lt;/a&gt;&lt;code&gt;18&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The stopwatch will begin when the method is called and end when the API returns the full data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To minimize anomalies and outliers, each operation will be executed 100 times, and the average call speed will be evaluated.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Specs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I7-9700k, 8 core, &lt;em&gt;4.6GHz&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Samsung SSD 840 EVO 250GB&lt;/p&gt;

&lt;p&gt;NVIDIA GeForce GTX 1070&lt;/p&gt;

&lt;p&gt;2x8 GB HyperX Fury 2666MHz DDR4 Memory&lt;/p&gt;
&lt;h2&gt;
  
  
  REST
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What is REST?
&lt;/h3&gt;

&lt;p&gt;We have decided to work with the common implementation of REST and not the &lt;a href="https://blog.ndepend.com/rest-vs-restful/" rel="noopener noreferrer"&gt;full implementation of a RESTful API&lt;/a&gt;&lt;code&gt;5&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The key features to take note of when using rest:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Separation of client and server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Server and client can be implemented independently without knowing each other-&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Server code can be changed without affecting the client.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Client code can be changed without affecting the server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Both server and client are aware of methods available.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Statelessness&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://restfulapi.net/statelessness/" rel="noopener noreferrer"&gt;Stateless&lt;/a&gt;&lt;code&gt;6&lt;/code&gt; means that the server is not required to know the current state of the client and vice versa.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Either end can understand any method calls, without knowing the previously called methods.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Invocation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;We invoke a method on the server via &lt;a href="https://www.restapitutorial.com/lessons/httpmethods.html" rel="noopener noreferrer"&gt;HTTP operations&lt;/a&gt;&lt;code&gt;7&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET&lt;/li&gt;
&lt;li&gt;POST&lt;/li&gt;
&lt;li&gt;PUT&lt;/li&gt;
&lt;li&gt;DELETE&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Setting up the experiment for the REST API
&lt;/h2&gt;

&lt;p&gt;The architecture for this experiment is a simple one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqgzbrhw5wt7atjqf7k4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgqgzbrhw5wt7atjqf7k4.png" alt="REST Architecture" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Sample project and metrics
&lt;/h2&gt;

&lt;p&gt;If you want to replicate this experiment yourself, the database setup can be found &lt;a href="https://github.com/NikoDyring/gRPC-vs-REST/blob/master/Database-scripts" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the source code for the rest-api can be found &lt;a href="https://github.com/NikoDyring/gRPC-vs-REST/tree/master/RESTForBlog2" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running our setup yielded the following results:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single payload&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The difference between a single small payload and a single large payload is small in the context of a daily task. A single small payload has a mean response time of 0.0181 whilst a single large payload has a mean response time of 0.0204 seconds. But in relation to each other, it's a 12.7% increase in response time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe60t018ga733h4y99d3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe60t018ga733h4y99d3b.png" alt="API Single Payload" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To put this into perspective a small payload contains 10 values of data. A large payload contains (4+(6*9))*6+4 or 352 values. This means that we have requested 3420% more data and it only took 12.7% longer.&lt;/p&gt;

&lt;p&gt;To test different scenarios we also created a "deep" payload that contains a different amount of nested objects. The deepest payload contains a total of eight nested objects, however, the total amount of values is far less in comparison to the previous payload. The previously mentioned payload peaked at 352 values whereas the deepest payload peaks at (4+(6*4))+(4+(7*4))+(4+(8*4)) values, or 96 values in total. In other words, the deep payloads are much smaller in size but different in structure.&lt;/p&gt;

&lt;p&gt;To give a concrete example, a large payload is structured like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;large_payload {
    id,
    string_Value,
    int_value,
    double_value,
    medium_payload {
        id,
        string_value,
        int_value,
        double value,
        small_payload {
                id,
                string_value,
                int_value,
                double_value
            },
        small_payload {
                ...
            },
        ...
        },
    medium_payload {
            ...
        },
    ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the deepest_payload is structured like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deepest_payload {
    id,
    depth_seven {
        ...
    },
    depth_eight {
        ...
    },
    depth_nine {
        id,
        string_value,
        int_value,
        double_value,
        depth_eight {
            id,
            string_value,
            int_value,
            double_value,
            depth_seven {
                ...
                depth_six {
                    ...
                    dpeth_five {
                        ...
                        depth_four {
                            ...
                            depth_three {
                                ...
                                depth_two {
                                    ...
                                    depth_one {
                                        ...
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interestingly, larger payloads returned faster results, an unexpected outcome that could hint at CPU scheduling effects or cached object reuse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F862ielrek8dqs8dovd6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F862ielrek8dqs8dovd6s.png" alt="REST Deep Payload Results" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To put things into perspective, a deep payload, which contains a total of 4+(4+4)+(4+4*2) values, or 24 values in total. Averaged at 0.0173 seconds, whereas the deepest payload, which carries a total of 96 values, which means it's 300% larger in size, averaged at 0.015 seconds. In other words, 300% more data was transferred 15.3% faster on average.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collection of payloads&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When we compare collections, the difference becomes very apparent. A small collection payload averaged 0.0256 seconds and a large average of 0.1006 seconds, which is an increase of 293%. It is apparent that when it comes to moving large collections of data over the REST API, it takes a considerate amount of time compared to smaller collections.&lt;/p&gt;

&lt;p&gt;The results are very much alike when we tested on collections of deep payloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl59t2865114q5k1v2rrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl59t2865114q5k1v2rrg.png" alt="REST Deep Payload Collection Results" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  gRPC
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is gRPC?
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt;&lt;code&gt;8&lt;/code&gt; is an open-source RPC framework, that can run in any environment. gRPC was recently included in the .Net core platform thereby easily accessible by thousands of developers.&lt;/p&gt;

&lt;p&gt;Some key features we would like to highlight:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP/2 support&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HTTP/2" rel="noopener noreferrer"&gt;HTTP/2&lt;/a&gt;&lt;code&gt;9&lt;/code&gt; is HTTP/1's successor, which is what most websites and frameworks utilize today. In many ways, HTTP/2 is an improved version of HTTP/1, and HTTP/3 is already in the works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Language independent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;gRPC is language independent, which means it doesn't matter which language you develop in. The framework supports a handful of &lt;a href="https://packages.grpc.io/" rel="noopener noreferrer"&gt;popular languages&lt;/a&gt;&lt;code&gt;10&lt;/code&gt;. This is quite an advantage when you're developing microservices, which might have services developed in different languages and frameworks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contract First&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;gRPC is strictly &lt;a href="https://en.wikipedia.org/wiki/Design_by_contract" rel="noopener noreferrer"&gt;contract first&lt;/a&gt;&lt;code&gt;11&lt;/code&gt; which is a design approach that works especially well in larger development teams. It also excels when developing microservices, as a contract would be created before any actual implementations can be done. The contract is designed in the &lt;a href="https://developers.google.com/protocol-buffers" rel="noopener noreferrer"&gt;.proto file&lt;/a&gt;&lt;code&gt;12&lt;/code&gt;, which is also where gRPC gains some of its speed from, seeing as .proto files are...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Strongly typed&lt;/strong&gt; As a by-product of a strongly typed proto file, which is used as a contract between client and server, but also used as an extensible mechanism for &lt;a href="https://en.wikipedia.org/wiki/Serialization" rel="noopener noreferrer"&gt;serializing&lt;/a&gt;&lt;code&gt;13&lt;/code&gt; structured data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up the gRPC project
&lt;/h2&gt;

&lt;p&gt;For the gRPC architecture we use the same as the rest, we have a client and a server running locally. The client calls the methods exposed by the proto file. The method then gets executed on the server and queries the database, once the data has been obtained it replies to the client. When the client has received all the data, we stop and log the time elapsed since the call started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbh0op8jg8mv96j00590.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbh0op8jg8mv96j00590.png" alt="gRPC Architecture" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample project and metrics
&lt;/h3&gt;

&lt;p&gt;If you want to replicate this experiment yourself database setup can be found &lt;a href="https://github.com/NikoDyring/gRPC-vs-REST/tree/master/Database-scripts" rel="noopener noreferrer"&gt;here&lt;/a&gt; and the source code for the grpc-project can be found &lt;a href="https://github.com/NikoDyring/gRPC-vs-REST/tree/master/GrpcProject" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running our setup yielded the following results:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Single payloads&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fst5drn7634dx3p8dktws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fst5drn7634dx3p8dktws.png" alt="gRPC Wide Payload Results" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test on single payloads yielded quite odd results, where the medium payload proved to be the fastest on average, and the largest payload only being slightly slower than the smallest. Just to recap the numbers; a larger payload contains 3400% more data than a small payload, and yet it only took 2.36% longer to get that data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bnwo4dgv68segywbesm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bnwo4dgv68segywbesm.png" alt="gRPC Deep Payload Results" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even more odd were the results of the deep payloads. Once again the payload containing a "medium" amount of data, was the fastest, just like previously. But unlike previously, the deepest payload was significantly faster than the deep payload, to be precise; the deepest payload, which contains 300% more data than a deep payload was 28.63% faster. As the results are rather unexpected we have to take a close look at possible errors that could have occurred.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Collection of payloads&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf6qguovkukjk7jdszmb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzf6qguovkukjk7jdszmb.png" alt="gRPC Wide Payload Results" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Collections paint a different picture, a small payload collection averaged 0.01911 seconds, while a collection of large payloads took 0.7025. This means a large payload on average took 267.6% longer to get. These results are much closer to what we would expect. We did the same test with a collection of deep payloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qn42vrxjub5cd2va1i4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2qn42vrxjub5cd2va1i4.png" alt="gRPC Deep Payload Collection Results" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The results of this test, were as you would expect, as the payloads incrementally increase in size, they also increase incrementally in response time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;When we put the two charts next to each other, it's easy to see which one has an edge. The REST API is represented by the blue blocks, whilst gRPC is represented by the red blocks, just like previously.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgafiqskc8d5b6yxcgnzt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgafiqskc8d5b6yxcgnzt.png" alt="Wide Payload results comparison" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrsrjb0hfr5fszbihfba.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftrsrjb0hfr5fszbihfba.png" alt="Deep payload results comparison" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the case for both single instances of objects as well as collections of objects.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3mxxchvh7ee3yhbmu05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3mxxchvh7ee3yhbmu05.png" alt="Deep payload collection result comparison" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex70w5nuemzgmk63ldci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex70w5nuemzgmk63ldci.png" alt="Wide payload collection result comparison" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We hypothesized that gRPC would be faster than the rest, based on the numerous blogs claiming this to be true, with their own tests. Contrary to popular belief, our experiments suggest that under certain conditions, REST can outperform gRPC in raw speed, reminding us that performance isn't universal but contextual.&lt;/p&gt;

&lt;p&gt;These results might not seem as much, but it has been &lt;a href="https://www.hobo-web.co.uk/your-website-design-should-load-in-4-seconds/" rel="noopener noreferrer"&gt;proven&lt;/a&gt;&lt;code&gt;14&lt;/code&gt; that people on average don't wait around for data to load and will abandon a web page or program if loading times are too long. When moving large amounts of data, a small amount of time can be the difference between keeping or losing a customer.&lt;/p&gt;

&lt;p&gt;this prompts the question: &lt;strong&gt;&lt;em&gt;When to use gRPC and when to use REST&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We would argue that gRPC fit into a setting, where you need to have multiple programs or services talking to each other across different languages, especially when the task that needs to connect to an endpoint is an action that needs to be executed; one such action could be TurnOnTheWater(). This argument is based on the research made into gRPC, rather than the results of these particular tests.&lt;/p&gt;

&lt;p&gt;REST on the other hand operates on the four aforementioned HTTP operations, these operations indicated data transfers of one sort or the other. While rest can execute the same actions as gRPC, the action TurnOnTheWater() doesn't fit into what a REST API was designed for. We would instead use REST where we required data transfers and other typical CRUD mechanics.&lt;/p&gt;

&lt;p&gt;Ultimately, the right choice depends on your use case: REST for simplicity and interoperability, gRPC for high-efficiency internal microservice communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible errors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Network outage during some of the tests&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The gRPC serverside logging was set to critical, tweaking this option might yield different results.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;This blog has only been about the differences in speed between REST and gRPC, but in reality, many other factors are present, if we were to truly compare the two frameworks. gRPC has claimed to not only be faster, but also more reliable, stable, and secure, and all of these metrics, as well as other metrics, would be interesting to cover, they are however out of scope in this particular blog-post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technologies used
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dotnet.microsoft.com/apps/aspnet/apis" rel="noopener noreferrer"&gt;.Net Web Api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/visualstudio/get-started/csharp/tutorial-console?view=vs-2019" rel="noopener noreferrer"&gt;.Net console app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;MySql Database&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.tutsplus.com/tutorials/rest-vs-grpc-battle-of-the-apis--cms-30711" rel="noopener noreferrer"&gt;Battle of the APIs&lt;/a&gt; &lt;code&gt;gRPC v REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/@bimeshde/grpc-vs-rest-performance-simplified-fd35d01bbd4" rel="noopener noreferrer"&gt;gRPC/REST performance simplified&lt;/a&gt; &lt;code&gt;gRPC v REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.yonego.com/nl/why-milliseconds-matter/#gref" rel="noopener noreferrer"&gt;Why milliseconds matter&lt;/a&gt; &lt;code&gt;gRPC v REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://medium.com/@EmperorRXF/evaluating-performance-of-rest-vs-grpc-1b8bdf0b22da" rel="noopener noreferrer"&gt;gRPC/REST evaluating performance&lt;/a&gt; &lt;code&gt;gRPC v REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://blog.ndepend.com/rest-vs-restful/" rel="noopener noreferrer"&gt;REST vs RESTful&lt;/a&gt; &lt;code&gt;REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://restfulapi.net/statelessness/" rel="noopener noreferrer"&gt;Statelessness&lt;/a&gt; &lt;code&gt;REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.restapitutorial.com/lessons/httpmethods.html" rel="noopener noreferrer"&gt;Http Methods&lt;/a&gt; &lt;code&gt;REST&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://grpc.io/" rel="noopener noreferrer"&gt;gRPC&lt;/a&gt; &lt;code&gt;gRPC&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/HTTP/2" rel="noopener noreferrer"&gt;HTTP/2&lt;/a&gt; &lt;code&gt;wiki&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://packages.grpc.io/" rel="noopener noreferrer"&gt;Suported gRPC languages&lt;/a&gt; &lt;code&gt;gRPC&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Design_by_contract" rel="noopener noreferrer"&gt;Design by Contract&lt;/a&gt; &lt;code&gt;wiki&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developers.google.com/protocol-buffers" rel="noopener noreferrer"&gt;Google proto buffers&lt;/a&gt; &lt;code&gt;gRPC&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Serialization" rel="noopener noreferrer"&gt;Serialization&lt;/a&gt; &lt;code&gt;wiki&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.hobo-web.co.uk/your-website-design-should-load-in-4-seconds/" rel="noopener noreferrer"&gt;Website should load in 4 seconds&lt;/a&gt; &lt;code&gt;blog&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dotnet.microsoft.com/apps/aspnet/apis" rel="noopener noreferrer"&gt;.NET Web API&lt;/a&gt; &lt;code&gt;.NET&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/visualstudio/get-started/csharp/tutorial-console?view=vs-2019" rel="noopener noreferrer"&gt;.NET Console App&lt;/a&gt; &lt;code&gt;.NET&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.mysql.com/" rel="noopener noreferrer"&gt;MySQL&lt;/a&gt; &lt;code&gt;MySQL&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.8" rel="noopener noreferrer"&gt;.NET Stopwatch API&lt;/a&gt; &lt;code&gt;.NET&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>grpc</category>
      <category>rest</category>
      <category>csharp</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
