Building REST APIs with C#, Go, Python, JavaScript

ยท

6 min read

Browsing around job postings with the query "Senior Software Engineer", a common responsibility that comes up is "Build out high-quality APIs and web services providing a scalable, efficient and tailored set of interfaces." This generic requirement, translated, is asking "can you build a REST API?" The "scalable, efficient and tailored set of interfaces" likely refers to the endpoints not exploding when many concurrent users hit it.

Most popular programming languages have their REST API frameworks:

  • Node has Express, Fastify and Nest

  • .NET has Active Server Pages (ASP)

  • Python has FastAPI, Flask and Django

  • Go has Echo, Fiber and Gin

  • Rust has Rocket and Rustless

I didn't list other languages here as I am less familiar with those, but out of the 5 listed above, I've tried most and there is one definite truth about them: They are all essentially the same.

There are differences between how Rust and Go, or Python and .NET handle stuff behind the scenes, but my hot take is not meant to compare lab benchmarks of all these frameworks. Instead, I'm talking about the dev and customer experience. Let's narrow it down a bit.

Dev Experience

Some of the above frameworks are a bit more complicated than others. ASP and Django are "batteries-included" frameworks, NestJS is more serious than Express and Fastify, while Echo and Fiber are overall less capable than Gin, but still have everything you'd ever need to write an API. At the core of these frameworks is their promise to serve REST requests. Here are some examples:

app := fiber.New()

app.Get("/", func(c *fiber.Ctx) error {
    return c.SendString("Hello, World ๐Ÿ‘‹!")
})

app.Listen(":3000")

Another:

const express = require('express')
const app = express()

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(3000)

And another:

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

One more:

from flask import Flask
app = Flask(__name__)

@app.route("/")
    def hello():
        return "Hello World!"

if __name__ == "__main__":
    app.run()

And last one...

#![feature(proc_macro_hygiene, decl_macro)]

#[macro_use] extern crate rocket;

#[get("/")]
fn index() -> &'static str {
    "Hello, world!"
}

fn main() {
    rocket::ignite().mount("/", routes![index]).launch();
}

As you can see in the above examples, these are all conceptually the same, simply different syntax since they're all written in different languages.

  1. Instantiate a server object

  2. Define a route, then add a handler to it.

Note: I'm not familiar with Rust, but wanted to include it since it's been all the rage recently.

ASP.NET is neat because it can get as simple or as complicated as you need it to be without needing additional 3rd party packages. The syntax above is called "minimal", but the framework supports the MVC pattern, dependency injection and more.

Node users will usually start with Express, then be told they're tools for using that and shown the light of Fastify. Once they switch to Fastify, they'll discover nobody actually uses it in serious production apps, because NestJS exists. Coincidentally, NestJS is built on top of Express/Fastify. Ah, the world of Node is a doozy.

Python has several good options too, with Django being the 1000 pound gorilla... but FastAPI and Flask are popular too. If you're a Go dev, you may first find Gin and then learn about Fiber.

If you're an entrepreneurial spirit thinking about starting your own SaaS, you may look at this list and collapse in a heap. But wait! Good news! It doesn't matter which one you choose, because the customer cares about the experience, not how that experience is delivered.

Customer Experience

Whether you go with ASP.NET, NestJS, Gin or Flask to deliver your API, the experience will be the same. The customer will get a Bearer token somewhere, toss it into the header, then send a GET or POST request to your API. They'll get a JSON response and be pleased. Sure, sure... in some cases, they'll send a GraphQL or a gRPC request (in which case you will want to make sure your framework supports these), but 98.4% of the time you'll serve a JSON response either directly to the customer or to your mobile or web app.

As I mentioned earlier, I'm not considering minute differences in performance when serializing huge data sets, or any kind of data transformation that might occur in the controllers/handlers of these frameworks. In most cases, data transformation should not be happening in the API anyway, or ideally, it shouldn't be happening "live" at all and if you're considering JSON serialization speed, you're designing your API incorrectly anyway (or you're Salesforce/Oracle and don't care about customer experience).

Customers make requests and receive responses. Regardless of the framework you use, your kickass new SaaS will be successful.

Parting Thoughts

If you've designed your cloud architecture correctly, the framework does not matter. If you're consciously building a monolith, you may opt for Django. If you're gonna be running several or several hundred microservices, Go, Flask, Fastify and Rustless are awesome choices. If you're writing a robust customer-facing API, NestJS and ASP.NET are great choices. You can even write everything in just one language and framework like ASP.NET, Express or Flask.

  • You won't need Rust's garbage collector-less performance advantages if you're just starting out. Don't sweat the details -- pick whatever is the quickest to be productive with.

  • Any decent software engineer (especially Sr level) can join your company and be productive with any of the above frameworks even if they have never used them or written any code in the language.

    I've been coding primarily in C# and JavaScript, but I picked up Go/Fiber in one week and then Python/Flask the week after. Once you're an expert in one language, other languages are a cakewalk. Truly.

  • I didn't mention meta frameworks like NextJS, NuxtJS and SvelteKit. These come with their own REST APIs that marry the backend and frontend technologies in one tech stack. These are all JavaScript/TypeScript and should strongly be considered especially if you're building a web app.

  • Before making a technology decision, take a step back and look at the big picture. Are you going to need to scale quickly? Do you have a mobile app and a web app? Are there microservices? Think about cron jobs or any ETLs you're gonna write. Is your product AI based (where you need to train your own models) or do you just plug into OpenAI or Bard? How about community and support?

At the end of the day, the API framework you choose for your customer facing product is irrelevant. The API framework you choose for backing microservices is mostly irrelevant (there are some less than optimal choices, but nothing that would sink your business). What you build your front-end in -- well, that may be a bit relevant... and about that in the next article!

Did you find this article valuable?

Support Paul K by becoming a sponsor. Any amount is appreciated!

ย