C# .NET 10 · gRPC · Protobuf · Azure

gRPC Weather Client

This C# web app (the client) gets the weather from a separate C# service (the server) using gRPC, Google's fast binary Remote Procedure Call framework. It also benchmarks gRPC against an ordinary REST call.

Run the gRPC vs REST benchmark

Get the weather via gRPC

This form calls the client's endpoint /weather?latitude=53.41&longitude=-2.15, which calls the server via gRPC. The server asks Open-Meteo and replies in Protobuf.

Server asleep? It scales to zero when idle. An HTTP call like /ping wakes it, but a gRPC call won't, and fails instead. Ping first, then try again.
Pick a place or enter coordinates, then press Get weather.

The reply includes raw_protobuf: the exact bytes the server sent. It is copied into the decoder below.

Benchmark: gRPC vs REST

The client fetches the same made-up hourly weather forecast from the server over REST (HTTP/1.1 + JSON) and over gRPC (HTTP/2 + Protobuf), and times each call. Each point is one hour of forecast: 12 fields (a time, 10 decimal numbers and a weather code), named like Open-Meteo's hourly forecast, so 10,000 points is about 14 months of hours. One point is about 290 bytes as JSON and 98 bytes as Protobuf. The server holds the data in memory, and both clients parse the reply into typed C# objects, so only the protocol and data format differ.

Three tests

Why the sizes matter

A tiny reply is almost all network round trip, so REST and gRPC tie (the first version of this benchmark only echoed 3 fields). With thousands of points JSON is about 3× bigger and slower to write and parse, and gRPC pulls ahead.

Settings

Change these in the address bar, i.e. /weatherbenchmark?sizes=1000,10000,50000&iterations=10. The results page explains every setting and why it has that value.

SettingDefaultWhat it does
sizes1,100,1000,10000Forecast points per reply, one results row each (up to 6 sizes, each up to 50,000)
iterations20Timed calls per protocol for each size
warmup3Untimed calls first, to open connections and warm up
parallel100Calls started at once in the burst test
parallelSize1000Points per reply in the burst test
streamSize10000Points in the streaming test

A default run takes about 30 seconds; Big replies takes over a minute.

How gRPC works

A high-performance, open-source Remote Procedure Call framework from Google (grpc.io). An app calls a method on a server on another machine as if it were a local object, which makes it popular for microservices.

How this demo works

  1. The browser calls the client (this C# app) at /weather.
  2. The client calls the server via gRPC: WeatherService.GetWeather.
  3. The server calls the free Open-Meteo API (no sign-up or key): forecast?…&current=temperature_2m,weather_code.
  4. Open-Meteo returns the current temperature (temperature_2m) and a WMO weather code (weather_code).
  5. The server replies to the client via gRPC, in Protobuf.
  6. The client turns the reply into JSON for the browser, with the raw Protobuf bytes alongside.

The proto contract

weather.proto is shared by the client and the server. It generates the C# code on both sides (or code in any other supported language). It defines:

Schema version
syntax = "proto3";
Data contract
WeatherRequest and WeatherResponse: the exact fields, types and field numbers sent between client and server. The benchmark adds ForecastRequest, ForecastPoint and ForecastResponse.
Service contract
WeatherService and its methods: GetWeather takes a WeatherRequest and returns a WeatherResponse. The benchmark adds EchoForecast and the streaming StreamForecast.
Wire contract
The field numbers (= 1, = 2) and types (double, string) fix the binary format, so it stays compatible across languages and versions.

Protobuf hex decoder

Paste the raw_protobuf value from Get the weather via gRPC to see the binary Protobuf message decoded into a WeatherResponse.

The decoded message will appear here.

Client endpoints

GET /
This page
GET /weather?latitude=…&longitude=…
The weather, fetched from the server via gRPC
GET /weatherbenchmark
Runs the gRPC vs REST benchmark and shows the results
GET /protos/weather.proto
The proto contract

About

Client (this app)
C# Web API on Azure App Service
Server
C# gRPC service in an Azure Container App (for HTTP/2): container-app-weather
Code
github.com/wizzard262/weather-via-grpc
Build and deploy
Azure DevOps pipelines

Diagram

Click to open full size in a new tab.

System diagram: browser, WeatherApi client, WeatherService server and Open-Meteo