zipDeploy vs runFromPackage — They’re Not the Same Thing
The Confusing Naming That Had Me Scratching My Head
I was reviewing one of our Azure DevOps pipelines this week and spotted what looked like a contradiction:
# In the Bicep template (app settings)
WEBSITE_RUN_FROM_PACKAGE: '0'
# In the pipeline (deployment task)
- task: AzureFunctionApp@1
inputs:
deploymentMethod: zipDeploy
My brain said: “Wait — WEBSITE_RUN_FROM_PACKAGE is 0 (disabled) but we’re using zipDeploy? Surely one of these is wrong?”
Turns out they’re both correct. The naming is just confusing.
Two Settings, Two Different Jobs
When deploying Logic App Standard (or Azure Functions), you typically have two stages:
- Infrastructure deployment — Bicep/ARM template that creates the Logic App resource and configures app settings including
WEBSITE_RUN_FROM_PACKAGE - Code/workflow deployment — Pipeline task (e.g.,
AzureFunctionApp@1) that pushes your zip package to Azure
These two settings control completely different things:
| Setting | Where It Lives | What It Controls |
|---|---|---|
WEBSITE_RUN_FROM_PACKAGE |
App Settings (Bicep/ARM) | Tells the runtime how to serve files |
deploymentMethod |
Pipeline task input | Tells the deployment task how to upload the package |
How zipDeploy Actually Works
When you use deploymentMethod: zipDeploy in your AzureFunctionApp@1 task:
- The task uploads your zip file to Kudu
- Kudu extracts the contents to
D:\home\site\wwwroot - Files are writable at runtime
The zip is just a transport mechanism — a convenient way to ship many files in one HTTP request. Once deployed, the zip is discarded; you’re left with loose files on disk.
How runFromPackage Actually Works
When you set WEBSITE_RUN_FROM_PACKAGE=1 in your app settings and use deploymentMethod: runFromPackage in your pipeline:
- The zip file is uploaded to
D:\home\data\SitePackages - The runtime mounts the zip directly as the
wwwrootfolder - Files are read-only at runtime — because you’re literally running from inside a zip archive
No extraction step. The app runs directly from the compressed package.
The Matrix of Valid Combinations
WEBSITE_RUN_FROM_PACKAGE |
deploymentMethod |
Result |
|---|---|---|
0 (or not set) |
zipDeploy |
✅ Extract files, writable wwwroot |
1 |
runFromPackage |
✅ Mount zip, read-only wwwroot |
0 |
runFromPackage |
⚠️ Works but contradictory |
1 |
zipDeploy |
⚠️ Works but contradictory |
The last two combinations will deploy successfully but create a mismatch between how files were deployed and how the runtime expects to serve them. Best avoided.
Why Use Each Approach?
zipDeploy (extract files):
- Writable filesystem — useful if your app needs to write temp files to wwwroot
- Familiar model — files on disk, easy to inspect via Kudu
- Slightly slower deploys on large packages
runFromPackage (mount zip):
- Faster deployments — no extraction step
- Atomic deploys — old package or new package, never a partial state
- Eliminates file-lock conflicts during deployment
- Reduced cold-start times (especially for apps with many files)
- Read-only wwwroot — a benefit or a constraint depending on your scenario
Putting It Together in Your Pipeline
Here’s what a consistent configuration looks like. First, in your Bicep template:
var appSettings = {
// ... other settings ...
WEBSITE_RUN_FROM_PACKAGE: runFromPackage ? '1' : '0'
}
Then in your Azure DevOps pipeline, match the deployment method:
# For runFromPackage: true (read-only wwwroot)
- task: AzureFunctionApp@1
inputs:
azureSubscription: $(azureSubscription)
appType: functionapp,workflowapp
appName: $(logicAppName)
package: $(Pipeline.Workspace)/logicapp/workflows.zip
deploymentMethod: runFromPackage
# For runFromPackage: false (writable wwwroot)
- task: AzureFunctionApp@1
inputs:
azureSubscription: $(azureSubscription)
appType: functionapp,workflowapp
appName: $(logicAppName)
package: $(Pipeline.Workspace)/logicapp/workflows.zip
deploymentMethod: zipDeploy
The key is consistency: if your Bicep sets WEBSITE_RUN_FROM_PACKAGE=1, use deploymentMethod: runFromPackage. If it’s 0 or not set, use zipDeploy.
Takeaway
If you see deploymentMethod: zipDeploy paired with WEBSITE_RUN_FROM_PACKAGE=0, don’t panic. They’re saying the same thing in two different contexts:
- Deployment time: “Upload a zip and extract it”
- Runtime: “Run from extracted files, not a mounted package”
The naming overlap is unfortunate — both involve the word “zip” or “package” — but once you understand that deploymentMethod controls how files arrive and WEBSITE_RUN_FROM_PACKAGE controls how files are served, it clicks into place.
Comments