Understanding parallelism in Terraform
By default, Terraform runs up to 10 operations concurrently. While this parallelism improves performance in many scenarios, it can cause issues with the Microsoft 365 provider due to:- Microsoft Graph API throttling limits
- Header map collision issues in the Kiota SDK HTTP client
- Resource contention when uploading and processing large files
Recommended Terraform settings
Setting appropriate parallelism
For Microsoft 365 provider operations, we strongly recommend reducing Terraform’s default parallelism to 1 to prevent API throttling and client-side errors:When to limit parallelism
Always use-parallelism=1 for both terraform plan and terraform apply operations.
Microsoft Graph imposes varying throttling limits across different services and operation types. During a typical Terraform workflow:
Planning phase
Terraform performs multiple GET requests to read current resource state, consuming API quota
Apply phase
Terraform executes CREATE (POST), UPDATE (PATCH/PUT), and DELETE operations, each with their own throttling limits
Environment variable configuration
You can set environment variables to enforce parallelism limits for all Terraform operations:Continuous integration considerations
For CI/CD pipelines, add explicit parallelism settings:GitHub Actions
State management best practices
Use remote state storage
Always use remote state backends for production environments. HashiCorp strongly recommends storing Terraform state remotely to enable collaboration, state locking, and secure access control.- State locking: Prevents concurrent modifications that could corrupt state
- Encryption at rest: Protects sensitive data in state files
- Team collaboration: Enables multiple team members to work on the same infrastructure
- Audit trail: Tracks who made changes and when
Enable refresh-only mode for drift detection
Useterraform plan -refresh-only to detect configuration drift without proposing changes. This is particularly useful for monitoring Microsoft 365 resources that may be modified outside Terraform:
Credential security
Never hardcode credentials
Never store credentials in Terraform configuration files or version control. Use one of these secure methods:Environment variables (recommended for local development)
Environment variables (recommended for local development)
Terraform Cloud/Enterprise Variables
Terraform Cloud/Enterprise Variables
Store sensitive values as sensitive variables in Terraform Cloud workspace settings. These are encrypted at rest and only decrypted during runs.
Azure Key Vault
Azure Key Vault
Managed identities (Azure environments)
Managed identities (Azure environments)
Apply least privilege principle
Grant only the minimum required Microsoft Graph API permissions to your service principal. Review and audit permissions regularly:- Start with read-only permissions during initial development
- Add write permissions only for resources you need to manage
- Use application permissions (not delegated) for unattended operations
- Document required permissions in your project README
Monitoring and logging
Enable debug logging for troubleshooting
When investigating issues with Microsoft Graph API calls, enable debug logging to capture detailed request/response information:Monitor API rate limit headers
The provider automatically handles retry logic, but you can monitor rate limit consumption by reviewing theRetry-After headers in debug logs. This helps identify resources that consume significant API quota.
Advanced configurations for large environments
For very large Microsoft 365 tenants (1000+ resources), consider these additional strategies:Use multiple workspaces
Split resources across multiple Terraform workspaces by service area (e.g., Intune policies, Conditional Access, users)
Use multiple client IDs
Distribute operations across multiple registered applications with separate throttling quotas
Summary
Always use-parallelism=1 when working with the Microsoft 365 Terraform provider. Microsoft Graph’s variable throttling limits across services mean that concurrent operations—whether during terraform plan (GET operations) or terraform apply (POST/PATCH/DELETE operations)—can quickly exhaust API quotas and trigger 429 errors.
Setting -parallelism=1 helps avoid:
- Server-side API throttling across all Microsoft Graph services
- Client-side header collision issues in the Kiota SDK
- Resource contention during file uploads and processing
Related resources
Microsoft Graph throttling limits
Official documentation on service-specific API rate limits
Microsoft Graph best practices
Microsoft’s recommended patterns for Graph API usage
Terraform state management
HashiCorp documentation on state files and remote backends
Terraform security
HashiCorp’s guide to secure Terraform usage
