We're awash in data. Today, we live in a digital world where data is produced and consumed at an unprecedented rate. Today's businesses rely on data to provide critical business insights and control operations and processes in real time. The traditional cloud computing models are constrained by their limitations in latency, bandwidth, and privacy to work with such massive volumes of data. Here's exactly where edge computing can help.
This article explores how you can use .NET to build edge-native systems, shorten latency, and keep data close to its source. It also discusses hybrid edge-cloud architectures, containerized microservices, messaging-driven architectures, local inference for IoT, and real-time sensor use, as well as complex issues of consistency, resilience, security, and observability.
To work with the code examples discussed in this article, you need the following installed on your system:
- Visual Studio 2026 (the Insiders channel supports .NET 11 release candidates)
- .NET 11 SDK (RC1 or later)
- Docker Desktop or another container runtime
- An Azure subscription with an IoT Hub and one registered IoT Edge device
- The Azure CLI with the azure-iot extension
- A container registry, such as Azure Container Registry (ACR)
If you don't already have Visual Studio 2026 installed on your computer, you can download it from https://visualstudio.microsoft.com/downloads/.
What Is Edge Computing?
Edge computing is a distributed computing paradigm that allows computers to do any or all of the data processing right at the point where the data is collected. It brings AI and analytics workloads near the originating source, thereby helping organizations make well-informed decisions, drive business growth, and innovate.
This is done by moving the computational workloads and data storage away from centralized data centers and cloud platforms to the edge of the network.
The data collected at the edge can be divided into three categories:
- Transient data: No action is required once the data is collected, and there is no need to store the data.
- Data to be retained: It is important to retain data collected at the edge so that it can be analyzed in the future.
- Time-critical data: The data collected at the edge calls for an immediate response.
The Internet of Things (IoT) and edge computing are classic instances of technological breakthroughs that are growing rapidly and regularly while also presenting a new set of challenges. The IoT ecosystem generates and distributes ever-increasing volumes of data, so computing, storage, and networking technologies must keep up with these developments and adapt to accommodate the needs of future workloads.
Why Do We Need Edge Computing?
In the traditional cloud computing paradigm, data is processed and stored in data centers that are centrally located, often far away from the consumers. As the amount of data grows exponentially, conventional cloud-based data processing methodologies face significant challenges.
The traditional computing paradigm is crippled by latency issues and network interruptions, making it challenging to work with such massive amounts of data in real time.
Figure 1 compares edge computing and cloud computing. While one uses a local platform to process data from devices and send only the results to the cloud, the other lets each device communicate directly with a remote data center. Therefore, every decision made on behalf of the device requires a network round-trip. Most latency associated with communicating with a remote data center comes from physical distance and the number of network hops required. Network congestion can also increase latency.

Edge computing uses a decentralized approach, processing data close to where it's generated. This improves response times, efficiency, and performance while reducing bandwidth consumption and operating costs. This is accomplished by moving data processing tasks to the immediate vicinity of the data sources, such as IoT sensors or local edge servers.
Local data processing eliminates a network roundtrip per decision, so you receive decisions much faster; i.e., the network latency will be lower. Also, because we send only results and/or alerts to the cloud, our cloud storage costs and bandwidth requirements will be lower.
Benefits
Edge computing offers several benefits:
- Lower latency: Edge computing facilitates reduced latency because there is no need for the data to travel to the cloud and back with each request.
- Lower bandwidth costs: Since you don't need round trips to a cloud server, and only the data that's needed is transmitted, edge computing can lower your bandwidth costs considerably.
- Resilient automation: Since automation will continue to operate regardless of the availability of the network, edge computing provides much more resilient automation.
- Data Privacy: By processing and analyzing data locally, potential threats during data transmission are reduced. Additionally, less data in transit means less data will be exposed thereby enhancing data privacy.
- Faster processing: Since most of the data is processed on-site, at or near the location of the data, you'll get results much faster without waiting for network connectivity.
- Scalability: Edge computing can grow over time, i.e., the number of edge nodes used can be increased, rather than increasing the amount of centrally located data center capacity. Essentially, edge computing enables organizations to scale at the edge by adding new hardware without investing additional resources in centralized data centers.
Simulate an Edge Device Using a .NET Background Service
Let's now simulate a simple edge computing application that demonstrates how you can collect temperature data and send critical alerts to the cloud after processing the data locally. For the sake of simplicity, we'll simulate an IoT device using an ASP.NET Core application.
Create a New ASP.NET Core Project in Visual Studio 2026
You can create a project in Visual Studio 2026 in several ways. When you launch Visual Studio 2026, you'll see the Start window. You can choose “Continue without code” to launch the main screen of the Visual Studio 2026 IDE.
- Start the Visual Studio 2026 IDE.
- In the Create a new project window, select ASP.NET Core Web API and click Next to move on.
- Specify the project name as
EdgeComputingDemoand the path where it should be created in the Configure your new project window. - If you want the solution file and project to be created in the same directory, you can optionally check the Place solution and project in the same directory checkbox. Click Next to move on.
- In the next screen, specify the target framework as .NET 11.0 (Preview) as shown in Figure 2, and the authentication type as well. Ensure that the Configure for HTTPS, Enable container support, and the Enable OpenAPI support and Use controllers checkboxes are unchecked because you won't use any of these in this example.

Create a new class named Worker in a file named Worker.cs and replace the autogenerated code.
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private const int AlertThreshold = 30;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task
ExecuteAsync(
CancellationToken stoppingToken)
{
//Not yet implemented
}
private double GetTemperature()
{
Random rand = new Random();
return 20 + (rand.NextDouble() * 15);
}
private void SendAlertToCloud
(double temperature)
{
_logger.LogCritical(
$"Sending critical alert: Temperature
{temperature:F2}°C");
}
}
The Worker class is the main worker component of the background service we'll implement. This class extends the BackgroundService class that handles all the complex lifecycle management operations such as starting, running in the background, and stopping gracefully for you automatically when your ASP.NET Core host starts.
Inside the Worker class are two members: a logger and a constant integer that represents the alert threshold. Note how we've used dependency injection to inject an instance of type ILogger<Worker> into the private logger field in the Worker class. Listing 1 shows the complete source code of the Worker class.
Listing 1: The Worker class
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private const double AlertThreshold = 30.0;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
_logger.LogInformation("Service started");
while (!stoppingToken.
IsCancellationRequested)
{
try
{
double temperature = GetTemperature();
_logger.LogInformation(
"Reading: {Temperature:F2} °C",
temperature);
if (temperature > AlertThreshold)
{
_logger.LogWarning(
"Alert: {Temperature:F2} °C",
temperature);
SendAlertToCloud(temperature);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process sensor data");
}
try
{
await Task.Delay(
TimeSpan.FromSeconds(2),
stoppingToken);
}
catch (OperationCanceledException)
{
break;
}
}
_logger.LogInformation("Service stopped");
}
private static double
GetTemperature() => 20 + Random.Shared.NextDouble() * 15;
private void SendAlertToCloud(
double temperature) => _logger.LogCritical(
"Sending alert: {Temperature:F2} °C", temperature);
}
The ExecuteAsync method is an overridden method where you should specify the exact operation your worker component should execute. We haven't implemented this method yet. The ExecuteAsync method accepts an instance of CancellationToken as a parameter. The runtime passes this instance to allow the code to stop executing when the application shuts down.
The following code snippet shows the ExecuteAsync method that reads the temperature and then checks if the current temperature exceeds the alert threshold. If that happens, it invokes the SendAlertToCloud method to send an alert to the configured cloud platform.
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
_logger.LogInformation("Service started");
while (!stoppingToken.IsCancellationRequested)
{
try
{
double temperature = GetTemperature();
_logger.LogInformation(
"Reading: {Temperature:F2} °C",
temperature);
if (temperature > AlertThreshold)
{
_logger.LogWarning(
"Alert: {Temperature:F2} °C", temperature);
SendAlertToCloud(temperature);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process sensor data");
}
try
{
await Task.Delay(TimeSpan.FromSeconds(2), stoppingToken);
}
catch (OperationCanceledException)
{
break;
}
}
_logger.LogInformation("Service stopped");
}
You should register the Worker background service as a hosted service in Program.cs:
builder.Services.AddHostedService<Worker>();
When you execute the application, the console output would look similar to this:
info: Worker[0]
Service started
info: Worker[0]
Reading: 33.68 °C
warn: Worker[0]
Alert: 33.68 °C
crit: Worker[0]
Sending alert: 33.68 °C
info: Worker[0]
Reading: 20.20 °C
How Does Edge Computing Work?
In edge computing, information is captured and processed close to where it originates. Here are the key activities that illustrate how edge computing works:
Data Generation
In the first step, data is generated by edge devices such as autonomous vehicles, IoT sensors, or mobile devices, which can generate massive amounts of real-time data. Traditional cloud computing processes data at a centralized data center, but edge computing processes data locally, close to the edge device.
Local Processing
Instead of transmitting all the data to a central data center or the cloud, the system processes it locally, on the device or on nearby edge servers or gateways.
Subsequently, only the essential data is transmitted to the central data center or the cloud, where it might undergo further processing or be retained for an extended period. This lowers latency and promotes real-time decision-making.
Filtering and Analysis
At this stage, data is filtered and analyzed at the edge of the network in accordance with predefined rules or algorithms. In this way, bandwidth usage is optimized since a reduced amount of data is sent to the cloud or data center.
Transmit Only Relevant Data
To minimize bandwidth requirements and data transfer volume, only relevant and critical data is sent to the cloud or data center for analysis and long-term storage.
Integration with Cloud-Based Services
Data that has been filtered and processed can be integrated with cloud-based services for advanced analytics, machine learning, or storage, enabling you to gain deeper insights, correlate your data, and store it for a long time.
Real-Time Decisions
With edge computing, real-time decision-making is made possible for critical monitoring systems, autonomous vehicles, and industrial automation by processing data locally and reducing round trips.
Key Challenges of Edge Computing
While processing at the edge has many benefits, edge computing brings a new set of challenges.
Bandwidth
As edge computing grows, so do its bandwidth requirements. Traditional networks allocate more bandwidth to data centers and less to endpoints, but edge computing needs more bandwidth at every endpoint, so its overall requirements are higher.
Latency
Most enterprises allocate more bandwidth to data centers than endpoints to keep bandwidth costs down. As the cloud pushes data to the edge while edge data goes the other way, uplink speed becomes a bottleneck. IoT traffic increases with the growth of the edge infrastructure over time, resulting in high latency due to insufficient bandwidth.
Security
Data security at the edge of the network can be tricky when processed by various devices that may not be as secure as centralized or cloud-based systems processed by a central server. With the increase in IoT devices, IT departments must be aware of potential security hazards.
Since edge devices are usually located in less secure environments than centralized data centers, they provide a much larger attack surface than centralized data centers. Hence, it is imperative that these remote devices are protected from tampering and compromise via appropriate security measures.
Key Components of Edge Computing Architecture
You should consider several factors when designing an edge computing architecture such as security measures, data processing requirements, and connectivity. The edge ecosystem includes edge devices, edge nodes, edge servers, edge gateways, and the cloud.
The key components of edge computing architecture are:
Edge Computing Infrastructure
An edge computing infrastructure consists of servers and edge data centers near edge devices. Typically, this includes computing resources, storage, and networking components such as edge or micro data centers.
Edge Devices
Edge devices refer to tangible items, including but not limited to IoT gateways, smart displays, point-of-sale terminals, drones, robots, etc. Edge devices, with little assistance from other components of the network, gather, analyze, and process data in real time from distant places situated at the edge of the network.
Edge Node
This is any device, server, or gateway that is able to perform edge computing. An edge node is defined as a virtual or physical machine situated at the edge of a network and acting as a gateway between local networks and the outside world.
In edge computing, edge nodes ensure that data can be efficiently processed, stored, and transmitted between local devices and central systems.
Edge Cluster/Server
These are servers located near end users that are used to deploy apps to devices. In contrast to servers located in a centralized data center, edge servers are located closer to end users, at the “edge” of the network. Bringing cloud computing resources closer to users reduces latency and allows faster response times.
Edge Gateway
An edge gateway is a piece of hardware or software that acts as a connection point between individual devices, local networks, and centralized systems such as the cloud. In essence, it acts as a connecting point closest to where data is generated and gathered at the “edge” of a network. This serves as an entry point to the cloud and performs network functions that include protocol translation, firewall management, etc.
Edge Applications
These refer to the software applications and services that run on the edge nodes/gateways or edge infrastructure that process, analyze, and respond to the collected data in real time, enabling real-time decision-making and actions at the edge.
Cloud
In terms of computing, the “cloud” is used to describe a distributed system of servers that houses applications and data on the internet rather than locally. Edge computing architecture is often integrated with cloud services to enable seamless communication between the edge and the cloud. With the help of cloud services, organizations and individuals can access and store data on remote computers situated in data centers all over the globe.
Pure Edge Vs. Thin Edge Vs. Thick Edge
Edge computing architectures differ in the distribution of resources and the degree of processing performed at the edge. There are three types of edge computing architectures: pure edge, thin edge, and thick edge.
Pure Edge
A pure edge architecture puts all the processing power, memory, and analytics on the edge devices. All data is processed locally, with only the relevant insights or results being sent back. As there's no need to transfer large amounts of raw data to the cloud, bandwidth usage and latency are minimal.
That's why pure edge computing is used for IoT sensors, gateways, mobile devices, and local servers with real-time, mission critical workloads.
Thin Edge
In thin edge architecture, a significant portion of the processing power of the cloud is shared with devices residing at the edge of the network. Edge devices process and filter data locally before they transmit the data to the cloud. Complex computation, data storage, and analytics are handled by the cloud.
Edge devices collect information and preprocess the collected data to lower the workload on the cloud. Thin edge computing can be helpful when processing power, cloud resources, and more advanced analytics are required.
Thick Edge
A thick edge architecture places additional computing, storage, and analytics functions at the edge. While edge computing enables sophisticated analytics, complex computation, and real-time decision-making, scalability, long-term storage, edge device communication, and synchronization continue to leverage cloud infrastructure. Thick edge computing is a good choice for smart factories, healthcare monitoring systems, or self-driving vehicles where you need more processing power at the edge devices and advanced analytics in the cloud. Figure 3 shows the differences between the types of edge computing architectures.

The Anatomy of Azure Edge Computing
Azure edge computing extends Azure services to edge devices, including IoT devices and gateways, to leverage computing, artificial intelligence, and analytics close to where the data originates or resides.
Azure IoT Edge is a device-focused runtime environment that enables you to deploy, execute, manage, and monitor containerized applications, thereby bringing analytics closer to your IoT devices for deriving insights faster and providing analytics and decision-making offline. The Azure IoT Edge architecture has three components:
- IoT Edge modules: These are essentially containers that execute Azure services, third-party services, or even your custom code.
- IoT Edge runtime: This is a runtime environment that executes on each IoT device and manages the modules that are deployed to each IoT device.
- A cloud-based interface: This enables you to manage and monitor your IoT Edge devices remotely.
Security at the Edge
We live in an incredible era where technology is everywhere; it surrounds us wherever we go. However, while technological advancements have made our lives more comfortable, they also create security vulnerabilities. Remember that any device or local network connection may be a weak spot.
If your critical data is scattered across such devices, you must have a proper strategy in place to keep your data safe and secure. Imagine that while your cloud server is your heavily guarded main bank vault, the edge devices are like dozens of smaller ATMs scattered throughout a network. You should ensure that each of these ATMs is authenticated and connects only to devices it is supposed to. Hence, we need to be able to secure our edge devices much the same way we secure applications and servers.
Credential management is yet another important security aspect. We often store secrets such as passwords and API keys in a secure location on a central server. However, because numerous small devices are spread across the network, securing these keys is critical. You must have a security strategy in place that ensures that if any of these keys are compromised, the damage is contained.
The following code snippet illustrates how you can retrieve secrets using token-based authentication.
public class SecureCredentialManager
{
private readonly HttpClient _httpClient;
private const string VaultApiUrl = "https://demovault.internal/v1/read";
public SecureCredentialManager(HttpClient httpClient)
{
_httpClient = httpClient;
}
public async Task<string> GetCredentials(string serviceIdentityToken)
{
var response = await _httpClient.GetAsync(
$"{VaultApiUrl}?token={serviceIdentityToken}");
if (!response.IsSuccessStatusCode)
{
throw new UnauthorizedAccessException("Authentication failed.");
}
var content = await response.Content.ReadAsStringAsync();
return ParseSecretValue(content);
}
private string ParseSecretValue(string content) => $"[SECRET_VALUE]...";
}
In the preceding code snippet, the vault endpoint points to a secure secret store. The GetCredentials method authenticates the service's identity via a token and returns temporary credentials. Lastly, this method returns only the required value, limiting exposure.
Zero trust security is a strategy often adopted to secure networks. The traditional way of thinking is that networks are protected. However, zero trust technology contradicts this idea by assuming you should never trust anything inside or outside the network. Essentially, in a distributed edge network, you must ensure that every request passing through the system is thoroughly checked for its origin, destination, and purpose.
Since zero trust security follows the principle “never trust, always verify,” this translates into the following policies:
- Microsegmentation; the network must be segmented.
- All traffic, internal or external, must have to go through an enforcement point (such as a service mesh sidecar) to verify the identity of every packet.
Performance and Scalability
Here are the key strategies you should follow to improve the performance and scalability of your edge applications:
Reduce Memory Usage and Garbage Collection (GC) Overheads
Although the garbage collector is a powerful component in any managed environment to clean up unused resources, it can often freeze your application when it cannot effectively keep pace with the volume of allocations. In a resource-constrained gateway performing complicated tasks, GC interruptions should be kept to a minimum.
Prefer structs over classes: Passing value types, such as struct instances, instead of reference types, such as class instances, reduces heap allocations and increases cache locality, easing GC pressure.
Consider the following piece of code that demonstrates a method called ProcessData that allocates many strings.
using System;
using System.Runtime.InteropServices;
public struct SensorReading
{
public double Value { get; set;}
public SensorReading (double value) => Value = value;
}
public List<SensorReading> ProcessData(byte[] rawBuffer)
{
string rawString = Encoding.UTF8.GetString(rawBuffer);
var readings = new List<SensorReading>();
foreach (var segment in rawString.Split('|'))
{
if (double.TryParse(segment, out double value))
{
readings.Add(new SensorReading{ Value = value });
}
}
return readings;
}
In the preceding piece of code, the foreach loop creates many temporary string objects.
The following code listing is an optimized version of the same method that uses ReadOnlySpan<T> for zero-copy access to the buffer segment.
using System;
using System.Runtime.InteropServices;
public readonly struct SensorReading
{
public double Value { get; }
public SensorReading(double value) => Value = value;
}
public List<SensorReading> ProcessData_Optimized(
byte[] rawBuffer, int offset, int length)
{
ReadOnlySpan<byte> span = new ReadOnlySpan<byte>(
rawBuffer, offset, length);
var readings = new List<SensorReading>();
int currentPos = 0;
while (currentPos < length)
{
int endOfSegment = Array.IndexOf(
span.Slice(currentPos).IndexOf((byte)'|'));
if (endOfSegment == -1) break;
ReadOnlySpan<byte> dataSpan = span.Slice(currentPos, endOfSegment);
if (double.TryParse(dataSpan, out double value))
{
readings.Add(new SensorReading(value));
}
currentPos = endOfSegment + 1;
}
return readings;
}
In the preceding code, the optimized ProcessData_Optimized method performs much better than the non-optimized version because there are no performance-degrading activities related to string processing, memory allocations, or encoding/decoding. The unoptimized method converts the input byte array (byte[]) into a managed string via Encoding.UTF8.GetString().
In contrast, the optimized version uses ReadOnlySpan so that each portion of the input buffer can be treated as a separate slice of byte buffer. Since the optimized version does not require any intermediate objects to be created, it avoids intermediate string allocations. Hence, it will significantly reduce both processing time and memory consumption, particularly when processing large amounts of data.
Enhance Startup Time with Native AOT
Edge devices reboot more often than servers do, since the service can be restarted for several reasons. The standard .NET runtime will have JIT compilation on every start. That's reasonable for a long-running cloud service but wasteful for a gateway that may restart dozens of times a day.
Native AOT compiles your application into native code during the publishing stage. There is no JIT or on-the-fly compilation at runtime, and you don't have to ship the .NET runtime together with your app since you have a complete standalone executable.
For an edge computing service, this means startup times measured in milliseconds rather than the hundreds of milliseconds typical of JIT-based console applications. The memory and disk savings matter on limited hardware. You need to enable Native AOT in the project file:
<PropertyGroup>
<PublishAot>true</PublishAot>
<InvariantGlobalization>true</InvariantGlobalization>
<TrimMode>full</TrimMode>
</PropertyGroup>
and then publish the project for your hardware platform using the following command:
dotnet publish -r linux-arm64 -c Release
It should be mentioned here that Native AOT has trade-offs: it doesn't support code paths that rely on reflection. Publish early to catch AOT-related errors before deploying to production.
Leverage Object Pooling
Instead of performing a series of object allocations (for example, HTTP request buffers, sensor reading packets), you should take advantage of object pooling to reduce the number of objects created in your application by reusing the objects from the pool.
Object pooling is extremely relevant in edge computing because these devices often have limited CPU cycles and memory bandwidth. Creating and destroying objects frequently leads to GC pauses, which are unpredictable delays that can cause real-time failures, a major concern at the edge. In a typical IoT or edge device, data processing involves receiving packets, buffering them in memory structures, performing calculations, and then releasing those structures.
For example, the following piece of code creates GC pressure because each time the new keyword is encountered, the runtime needs to allocate heap memory. Also, when the objects are discarded, the GC must clean them up, so it runs more frequently.
var packet = new SensorDataPacket(nextId++);
packet.ProcessData(...);
In a resource-constrained environment, this becomes challenging. Object pooling can solve this issue by maintaining a pool of ready-to-use, preinitialized objects. Object pooling works using these principles:
- Acquire: Borrow an object from the pool.
- Use: Use the object to perform the required operations.
- Release: Return the object to the pool when you're done with it.
Listing 2 demonstrates how you can use ObjectPool<T> from the Microsoft.Extensions.ObjectPool package to reuse sensor data packets, and ArrayPool<T> to rent and return byte buffers instead of allocating new ones.
Listing 2: Object pooling with ObjectPool and ArrayPool
using System.Buffers;
using Microsoft.Extensions.ObjectPool;
public sealed class SensorDataPacket
{
public int PacketId { get; init; }
public double[] Readings { get; } = new double[64];
public int Count { get; set; }
public void Reset() => Count = 0;
}
public sealed class SensorDataPacketPolicy
: PooledObjectPolicy<SensorDataPacket>
{
private int _nextId;
public override SensorDataPacket Create()
{
int id = Interlocked.Increment(ref _nextId);
Console.WriteLine($"[Pool] Creating packet {id}");
return new SensorDataPacket { PacketId = id };
}
public override bool
Return(SensorDataPacket packet)
{
packet.Reset();
return true;
}
}
public static class EdgeSimulation
{
private static readonly ObjectPool<SensorDataPacket>
Pool = new DefaultObjectPool<SensorDataPacket>(
new SensorDataPacketPolicy(),
maximumRetained: 16);
public static async Task
RunSimulationAsync()
{
double[] batch = [21.5, 22.25, 23.75];
for (int phase = 1; phase <= 2; phase++)
{
Console.WriteLine
($"--- Phase {phase} ---");
var tasks = new List<Task>();
for (int i = 0; i < 3; i++)
{
tasks.Add(ProcessBatchAsync(batch));
}
await Task.WhenAll(tasks);
}
}
private static async Task
ProcessBatchAsync(double[] batch)
{
SensorDataPacket packet = Pool.Get();
try
{
batch.CopyTo(packet.Readings, 0);
packet.Count = batch.Length;
await Task.Delay(50);
int id = packet.PacketId;
Console.WriteLine($"Packet {id}: {packet.Count} readings");
}
finally
{
Pool.Return(packet);
}
}
public static int ReadFrame(Stream source)
{
byte[] buffer = ArrayPool<byte>.Shared.Rent(4096);
try
{
return source.Read(buffer, 0, buffer.Length);
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}
}
}
Use Async and Await Judiciously
In a typical asynchronous programming approach, if a service makes a call to the network or reads the data from disk, it relinquishes control to the runtime, and other work (such as monitoring system state) can proceed in the meantime.
Assume that there is an edge gateway device that needs to read data concurrently from three different sensors (temperature, humidity, and GPS). Listing 3 shows how you can wait for the sensors without freezing the application. It demonstrates how you can read sensor data asynchronously from different local sensors over a slow serial bus or network connection.
Listing 3: The EdgeDataCollector class
using System.Diagnostics;
public class EdgeDataCollector
{
private static async Task<string>
ReadTemperatureAsync()
{
Console.WriteLine("Temperature Sensor: Starting read...");
await Task.Delay(TimeSpan.FromSeconds(2));
return "Temperature: 35.5°C";
}
private static async Task<string>ReadHumidityAsync()
{
Console.WriteLine("Humidity Sensor: Starting read...");
await Task.Delay(TimeSpan.FromSeconds(1));
return "Humidity: 65%";
}
private static async Task<string> ReadGpsAsync()
{
Console.WriteLine("GPS Sensor: Starting read...");
await Task.Delay(TimeSpan.FromSeconds(3));
return "GPS Coordinates: Latitude=17, Longitude=78";
}
public static async Task RunDataCollectionAsync()
{
Console.WriteLine("Edge Device Data Collection Started");
var stopwatch = Stopwatch.StartNew();
Task<string> temperatureTask = ReadTemperatureAsync();
Task<string> humidityTask = ReadHumidityAsync();
Task<string> gpsTask = ReadGpsAsync();
string[] results = await Task.WhenAll(temperatureTask,
humidityTask, gpsTask);
stopwatch.Stop();
Console.WriteLine ("All Data Collected Successfully!");
foreach (var result in results)
{
Console.WriteLine($"- {result}");
}
double seconds = stopwatch.Elapsed.TotalSeconds;
Console.WriteLine($"\nTotal execution time: {seconds:F2} s");
}
}
Asynchrony provides several benefits in edge computing:
- Non-blocking I/O: Edge devices usually use slow peripherals (such as serial ports and slow wireless connections) for communication. To keep CPU threads from sitting idle while waiting for sensor responses over unreliable connections, you can use
asyncandawait. While one sensor waits for a response, the CPU can continue other tasks, such as filtering local data or making inferences based on previously collected data. - Concurrency: You can take advantage of the
Task.WhenAll()method to parallelize multiple tasks, each of which reads data from sensors instead of executing the tasks sequentially. The overall processing time is determined by the slowest sensor, not the combined time of all sensors. - Efficient use of resources: In general, edge devices have lightweight processors (CPUs), so the use of asynchronous programming techniques helps lower CPU workloads by decreasing thread idle time.
Stream Data
Process the data as a stream rather than loading a whole file into memory. This is especially important if you are dealing with huge data streams. I/O operations, such as network reads or file creation and deletion, are generally slower than CPU processing, so design your application to avoid blocking the main processing thread during I/O.
Optimize Startup Speed
Edge devices may reboot rapidly due to power fluctuations, network problems, or failed updates.
Minimal Hosting
Use minimal APIs to reduce the resources needed to run ASP.NET Core applications; they're more efficient than other hosting models.
Prewarming
Preinitializing connections (connection pools, message brokers) ensures instant availability when the service receives its first request.
Use Profiling
Development can be misleading because development machines tend to be far more powerful than edge devices. Use the appropriate profiling methods that measure performance on embedded Linux platforms (such as perf and monitoring agents).
Thread Management
Ensure that the number of active threads does not exceed the number of cores since too many threads lead to unnecessary context switching overhead.
Observability
You should take advantage of structured logging and use correlation IDs to help analyze log messages regardless of which microservice created the message. The following code snippet illustrates how you can implement a simple logger for handling your log messages.
using System.Text.Json;
public class EdgeLoggerService
{
record LogEntry(string TraceId,
string ServiceName,
int SeverityLevel,
DateTime Timestamp,
string Message);
public void LogEvent(string traceId,
string service,
string message,
int severity)
{
var entry = new LogEntry(traceId,
service,
severity,
DateTime.UtcNow,
message);
string jsonOutput =
JsonSerializer.Serialize(entry);
Console.WriteLine($"[LOG] {jsonOutput}");
}
}
public void HandleIncomingRequest (Guid incomingTraceId)
{
string currentTraceId = incomingTraceId.ToString();
EdgeLoggerService logger = new EdgeLoggerService();
try
{
logger.LogEvent(
currentTraceId, "API_GATEWAY",
"Successfully received and started processing request.", 1);
}
catch (Exception ex)
{
logger.LogEvent(
currentTraceId, "API_GATEWAY",
$"Critical Error: {ex.Message}", 3);
}
}
Data Consistency Vs. Latency Trade-Off
Data consistency versus latency is a complex concept to understand. For example, there may be several copies of the same information at different locations along the network. One example could be information about the number of available resources or a patient's medical record data. Therefore, we require all copies of this data to be consistent, meaning they all keep providing the same version of the same information no matter when and where they were checked.
The trade-off is between the latency (i.e., the speed with which we can gain access to the information) and the consistency discussed above. Thus, we can either choose low latency and get fast access to the information and accept discrepancies in the data or accept higher latency to keep the data consistent.
Building Real-Life Edge Applications with .NET and Azure IoT
To build and deploy an edge application using Azure IoT, C#, and .NET, you should follow the steps outlined below:
- Set up the development environment
- Create your Azure IoT Edge application
- Test the Azure IoT Edge application
- Deploy the edge application
- Monitor and manage the Azure IoT Edge application
Using Azure IoT Edge Tools in Visual Studio
The Azure IoT Edge Tools are officially recommended tools from Microsoft for developing, testing, debugging, and deploying your Azure IoT Edge modules. You can use these tools from the command-line and in both Visual Studio 2022 and Visual Studio Code IDEs. The Azure IoT Edge tools help you to do each of the following:
- Create Azure IoT Edge projects that can target different platforms
- Add a new IoT Edge module locally
- Build and push Docker images of your IoT Edge modules
- Execute your IoT Edge modules in a remote or local simulator
To get started using Azure IoT Edge Tools in Visual Studio, download them from the Visual Studio Marketplace: https://marketplace.visualstudio.com/items?itemName=vsc-iot.vs17iotedgetools
If you're using Visual Studio Code, you can download the Azure IoT Edge tools for Visual Studio Code from here: https://marketplace.visualstudio.com/items?itemName=vsciot-vscode.azure-iot-edge
Install the vcpkg library manager using the following commands at the Windows Command Prompt:
git clone https://github.com/Microsoft/vcpkg
cd vcpkg
bootstrap-vcpkg.bat
Next, install the azure-iot-sdk-c package using the following commands:
vcpkg.exe install azure-iot-sdk-c:x64-windows
vcpkg.exe --triplet x64-windows integrate install
Next, download and install a Docker-compatible container management system on your computer. If you would like to develop modules using Linux containers, you can use Docker Desktop.
In the next step, create an Azure Container Registry or Docker Hub to store your module images. Next, install the Azure CLI on your computer. Note that you should have an active IoT Hub with a minimum of one IoT Edge device to test your module on a device.
Since the Azure IoT Edge tools for Visual Studio Code and Visual Studio are now in maintenance mode, Microsoft now recommends a command-line tool called
iotedgedev.
Create an Azure IoT Edge Project in Visual Studio
Follow the steps below to create an IoT Edge project in your Visual Studio IDE.
The process begins with creating a solution, which serves as a deployment package for the edge application.
- Launch the Visual Studio IDE.
- Select Create a new project.
- Search for the Azure IoT Edge template and select it.
- Select the required template and click Next.
- Specify the project name and location.
- Click Create to complete the process.
The Solution Structure
Visual Studio creates a solution that typically includes the following:
- Edge application project: The primary project that explains how the modules interact and what image compositions need to be applied.
- Module projects: These projects are subcomponents that typically represent containerized business logic.
You can right-click the working solution and select Add new project to create your module projects.
Containerization
Modules operating in the edge environment are organized in containers. You deploy the container, which includes the runtime environment and program, rather than the code alone.
Create a Dockerfile: The template might help you build a Dockerfile, but you may have to create it independently.
Describe the dependencies: The Dockerfile should give instructions to Docker about how to build a container.
Ensure that the connection string or identity settings of your module point to your IoT Hub (the name you created in Azure).
In the testing phase, Visual Studio generally makes use of simulated credentials. For actual deployment cases, you will need to ensure that the edge runtime installed on the physical device has the right security tokens to authenticate with the IoT Hub.
Right-click the solution and select the Build option to compile all the modules.
Test and Run the Application
Visual Studio allows you to run IoT Edge locally. You need to select Debug > Start Debugging (or use the specific button for Edge Device Simulator).
During simulation, the debugger will:
- Build the local Docker images for the modules.
- Run these images locally, making it possible to simulate the environment of the edge gateway.
- Provide you with the opportunity to control the module endpoints and see the data passing through the simulated connection to IoT Hub.
Deployment
In real-world deployments, you will use the Azure portal or infrastructure-as-code tools such as Terraform or Bicep to perform this task, while in Visual Studio you get to integrate all the process steps:
- Select the device group or IoT Hub connection to serve as your target.
- Employ the Publish/Deploy feature in Visual Studio to package all your Dockerized modules, together with their configurations, into an artifact bundle.
This uploads your app securely to the IoT Edge device group you selected, where the edge runtime downloads the required containers.
Monitor and Iterate
To check if your job is running, you need to return to the Azure portal at the Edge Jobs section to see the job you deployed on the portal.
Building and Deploying an Edge Module in .NET
To transition from the console demo that we implemented earlier in this article to something you would typically execute on your IoT Edge device, you will need the following three components:
- A module with the capability of communicating with the IoT Edge SDK via its message protocol.
- A container image for the module.
- A deployment manifest containing instructions regarding what modules should be executed by the IoT Edge runtime and what interactions are permitted among those modules.
Note that the standalone “Azure IoT Edge Tools for Visual Studio” extension was last updated in Visual Studio 2022 but can be used in Visual Studio 2026 as well.
The recommended method, however, for creating modules is the Azure IoT Edge extension for VS Code along with the Azure CLI's az iot edge commands. The steps below work with any editor.
Prerequisites
You need the .NET SDK (which you installed earlier in this article); either Docker Desktop or another container runtime that can be used to construct and execute the module images; the Azure CLI with the IoT extension installed (using the command az extension add --name azure-iot); and finally, an IoT Hub with at least one registered IoT Edge device for test purposes.
Writing the Module
An IoT Edge module is a .NET console application that uses Microsoft.Azure.Devices.Client to communicate with the IoT Edge runtime. The module will automatically use the injected environment variables provided by the runtime to connect to the runtime (there's no need to manage a connection string manually), receive incoming messages from an input channel, and send outgoing results to an output channel.
using System.Text;
using System.Text.Json;
using Microsoft.Azure.Devices.Client;
const double AlertThreshold = 30.0;
var moduleClient = await ModuleClient.CreateFromEnvironmentAsync();
await moduleClient.OpenAsync();
await moduleClient.SetInputMessageHandlerAsync(
"input1", async (message, _) =>
{
var payload = Encoding.UTF8.GetString(message.GetBytes());
var reading = JsonSerializer.Deserialize<SensorReading>(payload);
if (reading != null && reading.Value > AlertThreshold)
{
using var alert = new Message(
JsonSerializer.SerializeToUtf8Bytes(reading));
await moduleClient.SendEventAsync("output1",
alert);
}
return MessageResponse.Completed;
}, null);
await Task.Delay(Timeout.Infinite);
record SensorReading(double Value);
Note that “input1” and “output1” don't refer to specific topics; they're user-defined endpoints. With just a few changes in the deployment manifest, the user would be able to introduce filtering, have multiple data consumers, or replace a cloud endpoint with a local one without modifying any lines of code.
Containerizing the Module
Multistage builds limit the final image to what's required for execution (the published output), not the entire SDK. Since IoT Edge modules are distributed in container images, you will need a Dockerfile.
FROM mcr.microsoft.com/dotnet/sdk:11.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c release -r linux-arm64--self-contained -o /app
FROM mcr.microsoft.com/dotnet/runtime-deps:11.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["./EdgeAlertModule"]
Note that if you're using x64 edge hardware, you should use linux-x64 instead of linux-arm64, then append -p:PublishAot=true to the publish command. It should be noted here that a Native AOT build does not require a managed runtime to support it.
Native AOT is not tied to x64 architecture.
Build and publish to a registry that is accessible by your IoT Edge device using these commands:
docker build -t myregistry.azurecr.io/edge-alert-module:1.0 .
docker push myregistry.azurecr.io/edge-alert-module:1.0
Deploying and Connecting Routes
A deployment manifest is used by the IoT Edge runtime to determine which modules to deploy on a device and what routes those modules will take when communicating with each other.
The following minimal manifest deploys the module we just created as well as the standard built-in edgeHub module and route any alerts generated by our new module to the cloud.
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"modules": {
"edgeAlertModule": {
"type": "docker",
"settings": {
"image": "myregistry.azurecr.io/edge-alert-module:1.0"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"routes": {
"alertsToCloud": "FROM /messages/modules/
edgeAlertModule/outputs/
output1 INTO $upstream"
}
}
}
}
}
To deploy the manifest to your device, use the following command:
az iot edge set-modules --hub-name \
--device-id --content deployment.json
The runtime retrieves the image, launches the module, and creates a route; altering the method of communication among modules requires updating the manifest, rather than redeploying. Listing 4 shows the complete source code of the manifest.
Listing 4: Manifest to deploy edgeAgent and edgeHub system modules
{
"modulesContent": {
"$edgeAgent": {
"properties.desired": {
"schemaVersion": "1.1",
"runtime": {
"type": "docker",
"settings": {
"registryCredentials": {
"myregistry": {
"address": "myregistry.azurecr.io",
"username": "<acr-username>",
"password": "<acr-password>"
}
}
}
},
"systemModules": {
"edgeAgent": {
"type": "docker",
"settings": {
"image": "mcr.microsoft.com/
azureiotedge-agent:1.6",
"createOptions": "{}"
}
},
"edgeHub": {
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/
azureiotedge-hub:1.6",
"createOptions": "{}"
}
}
},
"modules": {
"SimulatedTemperatureSensor": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "mcr.microsoft.com/
azureiotedge-simulated
-temperature-sensor:latest",
"createOptions": "{}"
}
},
"edgeAlertModule": {
"version": "1.0",
"type": "docker",
"status": "running",
"restartPolicy": "always",
"settings": {
"image": "myregistry.azurecr.io/
edge-alert-module:1.0",
"createOptions": "{}"
}
}
}
}
},
"$edgeHub": {
"properties.desired": {
"schemaVersion": "1.1",
"routes": {
"sensorToAlert": "FROM /messages/modules/
SimulatedTemperatureSensor/
outputs/temperatureOutput INTO
BrokeredEndpoint(
\"/modules/edgeAlertModule/
inputs/input1\")",
"alertsToCloud": "FROM /messages/modules/
edgeAlertModule/outputs/
output1 INTO $upstream"
},
"storeAndForwardConfiguration": {
"timeToLiveSecs": 7200
}
}
}
}
}
Monitoring
You can use the following command to verify if a specific edge device is sending data as expected.
az iot hub monitor-events --hub-name <hub> --device-id <device>
While you can use this command to watch real-time messages from a specific edge device, it does not verify if the deployment was successful. To verify if the deployment was successful, you should use the following command instead:
az iot hub deployment show --hub-name <hub> \
--name <deployment> --device-id <device>
You can run the following commands on the device to know the module status, module logs, and a configuration check:
sudo iotedge list
sudo iotedge logs edgeAlertModule
sudo iotedge check
Edge Computing Vs. Cloud Computing Vs. Fog Computing
Although edge, cloud, and fog computing overlap, they're distinct paradigms that address different aspects of distributed computing. While they are based on distributed computing, focusing on provisioning computing and storage resources based on the data generated, they differ in terms of where the resources are located.
Edge computing and cloud computing are technologies that differ in terms of where the data is eventually processed. In the former, most of the data processing occurs at the network edge, whereas in the latter, data processing takes place at a central location. Edge computing does not replace cloud computing. These two technologies are not interchangeable. Rather than supplanting the cloud, edge computing works with the cloud to provide enhanced performance for processing time-sensitive data.
Fog computing, sometimes called edge fog computing, extends edge computing by introducing a distributed computing layer between edge devices and the cloud infrastructure. By using fog computing, you can bring certain cloudlike capabilities such as storage, computing, and networking closer to the edge, but not as close as with edge computing. It's well suited to smart cities, manufacturing, and healthcare, which need real-time analytics, data filtering, and intermediate processing.
While these technologies may share similarities, you must understand how they differ before deciding where to implement a set of logic. Edge computing extends processing as close to the actual source as possible; cloud computing does the opposite by transferring processing to the data center; fog computing is a kind of hybrid solution as it combines elements of edge and cloud computing and offers some additional services that are similar to those provided by cloud computing without making it completely cloud based. Edge computing doesn't replace cloud computing. Instead, it helps reduce the workload by processing time-sensitive data.
Applications of Edge Computing
Edge computing is well suited to industries where you need quick decision-making or have limited connectivity, including:
- Manufacturing: Edge computing is useful in the manufacturing industry because it enables devices at the edge to provide data to nearby machines, robots, and users without requiring a large amount of network bandwidth. Industrial scanners and sensors are used to monitor the production processes and determine if a defect occurred during production without waiting for data to reach the data center.
- Industrial IoT (IIoT): Edge computing is used in IIoT to perform intelligent manufacturing and predictive maintenance. In manufacturing units, sensors and other devices generate data that is used to improve product quality and reduce downtime. Predictive maintenance is only possible if certain sensors transmit information about vibrations and wear immediately.
- Smart cities: As a result of the exponential growth in the applications of cloud computing and edge computing, along with IoT, there is an increasing need to invest in more sustainable ways of living, such as building smart cities. Traffic signals and transit systems keep track of real-time developments, something that is impossible to achieve if one tries to limit the communication scope to a cloud-based center.
- Smart homes and virtual assistants: The advent of smart home technology has brought us many smart devices and a large amount of data that we can analyze quickly with increased accuracy, efficiency, and device integration. IoT ushers in a new era of bandwidth, latency, and security through improved technology and data processing.
- Autonomous cars: Edge computing processes data at the edge, which enables autonomous vehicles to make decisions and take action in real time. Autonomous vehicles must collect and process data on several parameters such as direction, speed, and location, which in turn must be processed in real time. If an autonomous vehicle has to utilize a cloud service to analyze the information provided by an external sensor, it can't function autonomously.
- Healthcare: Wearable devices can analyze data collected on the spot instead of sending it via an internet connection. The rapid response times enabled by lower latency can save lives in emergencies. Integrating edge computing and AI, including AI-assisted surgery, has significantly changed the healthcare landscape, revolutionizing its practices and outcomes.
The Future
The advent of edge computing and its subsequent surge have ushered in a new era of data analytics. Although it is still in its infancy, edge computing promises much in the coming years. To ensure reliability, edge computing requires high-speed connectivity since it depends on the cloud to process and store data.
With advances in semiconductor technology, microcontrollers (MCUs) and processors now have greater processing power, specialized hardware components, and computational capabilities. You can now deploy deep and convolutional neural networks at the edge and use them for faster analysis.
Edge computing is a technology that decentralizes intelligence, enabling developers to leverage .NET's unique features, including cross-platform capabilities, speed, and asynchronous techniques, to build resilient, low-latency systems that can operate independently in even the most challenging environments.
The edge ecosystem is not simply a combination of single nodes; it comprises a network of interlinked nodes that possess self-healing properties. In other words, it's a distributed system that implements local data processing to resolve global issues at an unprecedented speed. To succeed with edge computing, follow key principles such as asynchrony for resilience, containerization for flexibility, and zero trust for security.
Edge computing continues to mature; however, trends show that the cost of edge devices, for example, microcontrollers and processors capable of running convolutional neural networks locally, will continue to decrease, as will the cost of network connections to the cloud. Both trends are driving more workload from the cloud to the device.
The underlying principles that apply to each of these scenarios include using asynchronous I/O to keep slow sensors out of the critical path; containerizing your modules to allow independent updates and reasoning about each module; and defaulting to zero trust when transferring data over a network that may or may not be secure.
Takeaways
- Edge computing is a way of processing data closer to the location where the data is produced.
- Instead of sending all the data back to the central data center for processing, only the relevant information is transmitted to the central data center.
- Edge computing is being used to develop smart homes, where multiple devices can communicate with each other and execute commands instantly. With its great processing power and minimal latency, edge computing is ideal for use in home automation systems.
- Utilizing real-time analytics and machine learning methods, edge computing enables the continuous monitoring of critical decision-making processes.
- Use a
BackgroundServiceto run loops for devices and implement cancellation handling during the shutdown process for cleanliness. - Avoid hot-path allocations by using Span, ArrayPool, and ObjectPool.
- Use Native AOT or ReadyToRun to achieve faster startup times as long as you have verified that all of the dependencies in your project are compatible with AOT.



