Last week, the first Danish region in Azure finally opened, after being delayed in 2025.
Currently, only a subset of Azure features are supported. I recommend you visit azurecharts.com for the most up-to-date view of the products available: https://azurecharts.com/regions/?r=denmark-east
One thing is the products available. Another thing is the SKU’s. As a start, I realized that new new Azure App Service Premium v4 are not available. Only Premium v3 (Pv3) is available.
Unfortunately, I also found that my favorite Azure Function offering, Azure Flex Consumption, is not offered in the region yet.
Cost insights
I have made some analysis on the costs. It seems that costs are a quite a bit higher than comparable regions, West Europe, North Europe and Sweden Central. Here is an example for Azure App Services.
Since Pv4 is not available in Denmark East yet, I chose to look at the P0v3 Linux sku. Below is a comparison of the costs, from lower to higher, using the cheapest region, North Europe, as the index.
Region
Price (USD/Hour)
Index
North Europe
$0.08400
100 %
Sweden Central
$0,08900
106 %
West Europe
$0,08900
106 %
Denmark East
$0,10075
120 %
So the new region is 20 % more expensive than neighboring regions for Azure app service.
I also checked for Azure SQL and Azure Blob storage. In both cases, the prices were the same for all four regions. Lets hope the compute costs will go the same way.
Following receiving my MVP Award last month, I really wanted to go to the Microsoft MVP Summit in Redmond next year . However, the number of seats for In-Person attendance is limited, and you never actually know when registration opens – until it does.
I decided this was a great opportunity for me to test the Azure OpenAI services. The idea was to get the HTML body of the website which announces registration and make GPT parse the text and respond whether registration was open or not.
Azure Functions was a perfect fit for this. A Flex Consumption app that runs every 5 minutes with a timer trigger is one of the easiest things in the world to setup, and it has a very low cost.
Finally, I needed some way to get notified when registration opens. I considered using Azure Communication Services to send me a text message or a call, but it was too much of a hassle for this small project, as you need to register a phone number with a provider and pay for that number. Instead, I remembered that Home Assistant offers webhooks for automations, and since I have a Home Assistant Server at home and the Home Assistant companion app on my phone, that was a perfect match for this use case.
The Azure Function
The function runs on a timer every 5 minutes and performs the following steps:
Download HTML from the summit page
Run a fast keyword check (just because you can)
If inconclusive, call Azure OpenAI to classify the body content as OPEN or CLOSED
If OPEN, trigger a Home Assistant webhook which drives a mobile notification
Prerequisites
Azure OpenAI resource + deployed model (I used gpt-5-mini)
Function App (or local Function Core Tools) targeting .NET 8 isolated worker
<body> section is sent, which reduces token usage:
privateasync Task<bool>DetermineRegistrationOpenAsync(string html, CancellationToken ct){if(HeuristicCheck(html))returntrue;if(MissingOpenAiConfig())returnfalse;var body =ExtractBodyContent(html)??html;var chatClient =azureOpenAIClient.GetChatClient(_openAiDeployment);var messages =new List<ChatMessage>{new SystemChatMessage("You classify event registration state based on HTML body content. Reply only with OPEN or CLOSED."),new UserChatMessage(body)};var response =awaitchatClient.CompleteChatAsync(messages,ct);var answer =response.Value.Content.First().Text.Trim().ToUpperInvariant();returnanswer=="OPEN";}
Webhook notification
When registration is detected as open, a JSON POST to the Home Assistant webhook triggers a mobile push notification:
Create a new automation using the Webhook trigger. Here is my source:
alias:Summit registrationdescription:""triggers:-trigger:webhookallowed_methods:-POST-PUTlocal_only:falsewebhook_id:summit-registration-OMITTEDconditions:[]actions:-device_id:OMITTEDdomain:mobile_apptype:notifytitle:Summit registration open!message:Registration is opendata:actions:-action:URItitle:Open Urluri:https://summit.microsoft.com/en-us/mode:single
Security notes
Webhook URL should be treated as a secret.
Final notes
Most of my code was written with GitHub copilot in Agent mode with GPT-5
My costs to run this for a few days, including the Azure AI Foundry containing the gpt-5-mini model, added up to ~0.1 USD per day. And since it was announced one week ahead that registration would open some time this week, it added up to less than $1 to have this running for me.
Azure Flex Consumption Functions went GA in November 2024. We have been using them extensively since they came out in public preview in May 2024, and we are very happy about this addition to the Azure Function SKU options.
When considering moving your Azure Functions to Flex Consumption, some limitations must be considered. These are described in the Flex Consumption hosting documentation. However, in some cases, the limitations can be mitigated. Below, I will describe how to mitigate some of the limitations with very few lines of code.
Load certificates for HttpClients
In Flex Consumption, it is currently not supported to load certificates from the managed certificate store using the app setting linked to an Azure Key Vault certificate.
However, you can still access Key Vault certificates from your Functions in Flex Consumption if you need to.
A very common use case is to load the certificates from a key vault to use them with client certificate authentication in an HttpClient. To solve this use case in a Flex Consumption app, you can refer to the certificate in from a key vault using the secret URL of the certificate. If you refer to the secret URL of a key vault certificate, you get the certificate as a Base64-encoded string, which you can decode and add as a client certificate when you configure your client. In your app settings, e.g. in Bicep, refer to the secret like this:
Notice the /secrets/ path in the URL and not /certificates/. Even though this is stored as a certificate in the vault, you can access it through the secrets API to retrieve it as a Base64 encoded string.
Then, using the Base64 encoded string in an app setting, you configure the HttpClient as follows in your Program.cs:
On Flex Consumption, I have found that the set of default TLS Cipher Suites is more restrictive than what is configured per default in Consumption and Premium plans. If you see errors from the runtime like Interop+Crypto+OpenSslCryptographicException and The SSL connection could not be established, see inner exception. Authentication failed, see inner exception. SSL Handshake failed with OpenSSL error - SSL_ERROR_SSL. error:0A000410:SSL routines::sslv3 alert handshake failure when calling and external API’s that do not support TLS1.3, I suggest you try the following:
WARNING: The code below will modify, and, most likely, weaken, the security of your outbound HTTP calls. Only do this if you have to, and have no control over cipher suites of the remote API.
Configure the TLS Protocol and Cipher Suites on the HttpClient handler using the SocketsHttpHandler as shown below:
using System.Net.Security;using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Hosting;var host =new HostBuilder().ConfigureFunctionsWebApplication().ConfigureServices(s =>{s.AddHttpClient("tls1.1").ConfigurePrimaryHttpMessageHandler(()=>new SocketsHttpHandler(){SslOptions=new SslClientAuthenticationOptions{EnabledSslProtocols=System.Security.Authentication.SslProtocols.Tls12|System.Security.Authentication.SslProtocols.Tls13,CipherSuitesPolicy=new CipherSuitesPolicy(new[]{// DefaultTlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TlsCipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,// Additional suites (replace with your own)TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TlsCipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TlsCipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,TlsCipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,TlsCipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TlsCipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TlsCipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,TlsCipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA,TlsCipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,TlsCipherSuite.TLS_AES_128_GCM_SHA256,}),},});}).Build();awaithost.RunAsync();
Accessing network-restricted Key Vaults
A current limitation of Flex Consumption at the time of writing (April 2025) is that you are unable to access secrets in a network-restricted Azure Key Vault through by using the SecretUri reference in the app settings of the Function App as follows: Microsoft.KeyVault(@SecretUri=https://myvault.vault.azure.net/secrets/mysecret)
Instead, you can use the Key Vault SDK to retrieve the secrets from code with the following code in your Program.cs: