Introduction
Last week I faced a particular issue during an Azure Function deployment. I had two Azure Functions (f1 and f2). I’ve been doing deployments to f1 for a while without any issues. However, recently I added a new f2. I created the ADO pipeline to deploy to f2 and I ran it. When the deployment was completed, f2 looked good, but f1 stopped working. All functions deployed to f1 had gone. f1 had the same functions deployed as f2.
Initially I thought there was a typo in the f2 deployment pipeline, so I checked the logs. Everything was right. Connection and Function names were pointing to f2, not f1… After a couple of hours of debugging I found both Function Apps were sharing the same file share, and that was causing the issue. Let me explain why and how to fix it…
Architecture
For context, these were the resources I had:
- A Linux App Service Plan.
- Two Function Apps hosted in the same Plan.
- A Storage Account to store runtime files for Azure Functions (this is defined using the
WEBSITE_CONTENTSHAREandWEBSITE_CONTENTAZUREFILECONNECTIONSTRINGsettings).
How Azure Functions Use File Shares
During the creation of an Azure Function it’s required to specify a Storage Account as part of the set up. Azure Function uses this Storage Account for these purposes:
- Storing function code
- Internal logs and metadata
- Host runtime files
The link between a Function App and a Storage Account is done using these settings:
WEBSITE_CONTENTSHARE: Sets the name of the file share used by the Function App.WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: Sets the connection string of the Storage Account so the Function App can connect to the file share.
Why Sharing the Same File Share Causes Conflicts
When two or more Function Apps share the same File Share you will get issues such as:
- Overriding function code.
- Missing function files.
- Failures after deployments.
- Cold starts or random restarts.
- One app works, but the other fails.
This happens due to the following reasons:
- Race conditions: Functions try to use the same wwwroot folder, so we get undefined behavior.
- File locks: One runtime can lock a file while the other tries to access it.
- Deployment collisions: one deployment can use ZIP deploy while another uses run-from-package.
- Scaling out effects: Adding more instances of a Function App amplifies the issue.
The Fix
At this point it should be clear that the solution is that each Function App should use its own file share. It can be in the same Storage Account or in a different Storage Account.
Make sure the WEBSITE_CONTENTSHARE is different for each Function App. As a good practice don’t hardcode the value of this variable, instead use this format in your IaC: ${functionAppName}-content.
If you prefer a quick visual explanation, here’s a short walkthrough showing the issue and the fix: Watch the YouTube Short