Blog

Measuring Your Azure Carbon Footprint with the Sustainability API

08 Feb, 2024
Xebia Background Header Wave

So, you want to start with green software on the Azure cloud by measuring your carbon footprint. But where to start? Microsoft Azure’s Sustainability API can help organizations measure their carbon footprint to analyze and reduce it. In this blog, we’ll dive into the carbon emission data it offers and how it can be leveraged for a more sustainable future. But first, an overview.

Overview Azure’s Sustainability API

The Azure Sustainability API is part of the broader Microsoft Cloud for Sustainability (MCfS), a suite of tools designed to help organizations track, manage, and reduce their environmental impact. Before using the API, some prerequisites are discussed in detail on the following page: https://learn.microsoft.com/en-us/industry/sustainability/api-overview. You have the choice between an OData API and an Export API. Let’s break down the JSON output from the OData API call to get the emissions and understand the information it provides. Please note that the API is in preview as of this writing, and the documentation is incomplete. So, some descriptions are my interpretation of the data. From my perspective, let’s look at the most exciting endpoint in this blog post: The EmissionsByEnrollment endpoint!

Dissecting the EmissionsByEnrollment Endpoint

The HTTP GET request to get emissions by enrollment, which is the only option at the moment of writing this as far as Azure is concerned, looks as follows: https://api.mcfs.microsoft.com/api/v1.0/instances/{instanceId}/enrollments/{enrollmentId}/emissions[?$apply][&$filter][&$select][&$orderby][&$expand][&$top][&$skip][&$count] and is called ‘EmissionsByEnrollment’. We fill in the ‘instanceId’ we created earlier, as described at the provided link, and fill in the ‘enrollmentId’ (read ‘billingId’). We’ll leave the other parameters for now. When we make the call, we receive an EnrollmentEmissionCollection, which consists of EnrollmentEmission objects that look as follows in JSON format:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "rowNum": 1234,
  "dateKey": 20230201,
  "enrollmentId": "GUID1:GUID2_YYYY-MM-DD",
  "orgName": "",
  "subscriptionId": "GUID",
  "subscriptionName": "Subscription Name",
  "azureServiceName": "Azure Monitor",
  "subService": "Azure Other",
  "azureRegionName": "North Central US",
  "scope": "Scope1",
  "scopeId": 1,
  "totalEmissions": 3.3200622506179E-08,
  "pk": "dataKey + 1 + subscriptionID + subService"
}

To properly deserialize the EnrollmentEmission JSON object, you’d make the following class in C#.NET:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
internal class EnrollmentEmission
{
    [JsonProperty("rowNum")]
    public int RowNum { get; set; }
    [JsonProperty("dateKey")]
    public long DateKey { get; set; }
    [JsonProperty("enrollmentId")]
    public string EnrollmentId { get; set; }
    [JsonProperty("orgName")]
    public string OrgName { get; set; }
    [JsonProperty("subscriptionId")]
    public string SubscriptionId { get; set; }
    [JsonProperty("subscriptionName")]
    public string SubscriptionName { get; set; }
    [JsonProperty("azureServiceName")]
    public string AzureServiceName { get; set; }
    [JsonProperty("subService")]
    public string SubService { get; set; }
    [JsonProperty("azureRegionName")]
    public string AzureRegionName { get; set; }
    [JsonProperty("scope")]
    public string Scope { get; set; }
    [JsonProperty("scopeId")]
    public int ScopeId { get; set; }
    [JsonProperty("totalEmissions")]
    public double TotalEmissions { get; set; }
    [JsonProperty("pk")]
    public string Pk { get; set; }
}

The C#.NET class for the EnrollmentEmissionCollection object looks as follows:

1
2
3
4
5
6
7
8
9
10
11
internal class EnrollmentEmissionCollection
{
    [JsonProperty("@odata.context")]
    public string Context { get; set; }
    [JsonProperty("value")]
    public List<EnrollmentEmission> Value { get; set; }
    [JsonProperty("@odata.nextLink")]
    public string NextLink { get; set; }
}

Beware! You get all the emissions from all the subscriptions under the provided enrollment ID per subscription and resource type. So, for instance, if you have Virtual Machine “foo” and Virtual Machine “bar,” their emissions will be lumped together under the service name Virtual Machine per subscription. It’s not ideal if you want to start carbon optimizing your software architecture.

My interpretation of the information held in each field of this output is as follows:

  • rowNum: A sequential identifier for the data row within a dataset, ensuring easy reference and management. In this case, the row number is 1234.
  • dateKey: The date associated with the data, formatted as YYYYMMDD. This entry, 20230201, indicates that the data is for February 1st, 2023. Please note that, as far as I could observe, the data is stored monthly. This means you can only monitor changes in carbon emissions per month!
  • enrollmentId: A unique identifier for a specific enrollment or account within Azure, comprising two GUIDs and a date. Better known as the billing ID.
  • orgName: The organization’s name associated with the data (in my tests, this always seemed empty).
  • subscriptionId: A unique identifier for an Azure subscription.
  • subscriptionName: A user-friendly name for the Azure subscription.
  • azureServiceName: The specific Azure service being used, here “Azure Monitor”.
  • subService: The specific sub-service utilized within the broader Azure service. In this example, labeled as “Azure Other” in a service that might not fit into predefined categories or is miscellaneous.
  • azureRegionName: The geographic location of the Azure region where the service is deployed. “North Central US” is specified for this record, indicating the physical location of the infrastructure.
  • scope: This denotes the scope of carbon emissions based on the Greenhouse Gas (GHG) Protocol corporate standard. “Scope1” emissions represent direct emissions from owned or controlled sources, such as the cooling systems used at data centers.
  • scopeId: A numerical identifier corresponding to the emission scope, here 1 for Scope 1 emissions.
  • totalEmissions: The total carbon emissions (measured in metric tons of CO2 equivalent) associated with the specified resources or services for the given time frame. The total carbon emissions value 3.3200622506179E-08 is 0.000033200622506179004 kgs CO2eq.
  • pk: Likely stands for ‘primary key,’ a unique identifier for the record. This value seems to concatenate the ‘dateKey, the number ‘1’ for some reason, ‘subscriptionId’, and ‘subService’, used for ensuring uniqueness and possibly for indexing purposes. It is used in the ‘nextLink’ property of EnrollmentEmissionCollection, which you can read about in the next paragraph.

The OData API provides a ‘nextLink’ to get the next EnrollmentEmissionCollection. An EnrollmentEmissionCollection contains a maximum of 1000 EnrollmentEmission objects. A typical ‘nextLink’ looks like: https://api.mcfs.microsoft.com/api/v1.0/instances/{instanceId}/enrollments/{enrollmentId}/emissions?$skiptoken=pk-{ dataKey + 1 + subscriptionID + subService }. The skip token will be the last primary key (pk) of the last EnrollmentEmission. Every EnrollmentEmissionCollection also contains an OData ‘context’ property, which looks like: https://api.mcfs.microsoft.com/api/v1.0/instances/{instandeId}/enrollments/{enrollmentId}/$metadata#emissions. In this case, the metadata indicates a call to ‘EmissionsByEnrollment’.

So how does Microsoft calculate the field ‘totalEmissions’ on Azure?

Microsoft’s Method for Carbon Emissions Calculation

As said earlier in this blog, the API returns scopes (see: ‘scope‘). Microsoft’s methodology for calculating carbon emissions aligns with global standards like the GHG Protocol. The process encompasses:

  • Scope of Emissions: Including all three scopes ensures a comprehensive view of emissions.
  • Data Collection: Gathering usage data from Azure services (there’s a separate endpoint for usage data, which I’ll look at in my next blog post).
  • Emission Factors: Applying region-specific emission factors to reflect the actual carbon intensity.
  • Carbon Accounting: An approach for covering direct emissions (Scope 1), indirect emissions from purchased energy (Scope 2), and other indirect emissions (Scope 3).
  • Calculation and Reporting: Aggregating data to calculate the total carbon emissions, which are then reflected in the totalEmissions field in the JSON output described before.
  • Continuous Improvement: Ensuring the methodology gets better and better at carbon accounting through constant refinement and third-party validations. They are also continuously getting more and better information on embodied carbon from other parties.

This approach forms the backbone of the data provided by the Sustainability API, enabling an assessment of your carbon footprint. However, the impact of these carbon emissions can only be measured when considering the complex context of software. That is where GSF’s SCI specification could help.

GSF’s SCI Specification

The Green Software Foundation’s SCI specification provides a standardized approach to measuring the carbon impact of software. It helps understand and improve the sustainability of your digital solutions. The SCI is calculated as:

SCI=(O∗E∗I)/R

Where O represents operational emissions, E is the energy proportion, I denotes the location-based carbon intensity, and R is the baseline for normalization.

The ‘totalEmissions’ field from Azure’s Sustainability API can be a critical input in calculating the SCI score on Azure. By comparing the operational emissions (O) with the total energy used (another endpoint we’ll discuss another time) and the carbon intensity of the energy source, organizations can obtain a nuanced understanding of their software’s carbon intensity. When tracked over time, this metric can guide strategies to reduce the carbon footprint, aligning operational efficiency with sustainability. As said earlier, when discussing the ‘dataKey’, you’ll have to be patient because the data is provided once a month, so it seems to me. A blog post with a worked-out example of calculating SCI is being worked on at the moment of writing this.

Now, we know how to measure the true impact of our software’s carbon footprint. How could organizations leverage this data?

Leveraging the Data

Understanding your carbon footprint is just the first step. The real power lies in using this data to make informed decisions. Here are some ways organizations can leverage this data:

  • Optimization: Identify services or resources with high emissions and explore ways to optimize their usage or switch to more efficient alternatives. This could be as simple as deploying your resources to another region, which The Green Software Foundation (GSF) calls: “Carbon Awareness.” Or start up a batch process at a time with low carbon intensity, which is known as ‘time-shifting,’ a term coined by GSF. Or do less work when the carbon intensity is high; do more when the carbon intensity is low, which is ‘time shaping’ according to GSF.
  • Strategic Planning: Using the data for long-term planning, ensuring sustainability is critical in future infrastructure developments or expansions. Integrate GreenOps in’ your culture. Easier said than done, of course. Let transparency about your carbon footprint be the first step.
  • Reporting & Compliance: With increasing regulatory focus on environmental responsibility, this data can be invaluable for reporting and ensuring compliance with various environmental standards. The Corporate Sustainability Reporting Directive (CSRD) comes to mind.

Thus, data becomes information that organizations can use to make strategic decisions.

The Road Ahead

As we journey towards a more sustainable future, tools like Azure’s Sustainability API will play a pivotal role. They bridge the gap between digital transformation and environmental stewardship, empowering organizations to be accountable for their carbon footprint and take proactive steps to reduce it.

Also, keep an eye out for the following page: https://learn.microsoft.com/en-us/azure/architecture/example-scenario/apps/measure-azure-app-sustainability-sci-score. As there are a lot of dynamics on the front of Software Carbon Intensity (SCI) scoring and the data available on Microsoft Azure.

Now get yourself an MCfS instance running and measure some carbon emissions!

Danny van der Kraan
As a Green Software practitioner, I'm dedicated to harnessing the power of code to benefit both our digital landscape and the environment. With a deep passion for software engineering, I specialize in crafting robust distributed systems, encompassing microservices, Domain-Driven Design (DDD), messaging, event sourcing, CQRS, and serverless technologies. Recently, I've delved into AI and Data, continually expanding my skill set. My mission is to assist my clients in adopting sustainable best practices on the Azure cloud, creating a win-win situation for businesses and the planet. Follow my journey and stay updated on my progress at dannyvanderkraan.com.
Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts