I'm a DevOps & Platform Engineer on enterprise projects: CI/CD, Kubernetes, Terraform, cloud cost.
I wrote application code before I ran the infrastructure that hosts it, which pays off mostly when a build breaks and someone has to know where to look.
The open-source work here comes from the same place. Something misbehaves in a real deployment, I go read the source, and the fix goes upstream rather than into a patch I keep to myself.
role: DevOps & Platform Engineer
platform: [Azure, Kubernetes, GitOps, Terraform, Azure DevOps, GitHub Actions]
also: [FinOps, Agentic DevOps, .NET backend]
languages: [C#, TypeScript, Go, Rust, Python, Bash, PowerShell]
into: [correctness bugs, observability gaps, release plumbing, cloud cost]
based_in: Turin, Italy|
Platform & CI/CD Azure DevOps YAML pipelines and reusable templates · GitHub Actions · Helm charts and Helmfile releases · OCI push to ACR/GHCR · ApiOps policy automation on Azure API Management · Jinja2 templating · branch policies, PR review, code review as a gate |
Cloud & infrastructure Kubernetes on AKS and k3d on-prem · NGINX Ingress Controller · Terraform (azurerm, azuredevops) · VM Scale Sets as self-hosted agent pools · golden images for faster scale-out · Container Registry, Storage Accounts, Functions, Entra · reservation and cost governance |
|
Backend & architecture REST/HTTP APIs in .NET 8/9 · Worker Services · CQRS with MediatR · Domain-Driven Design · hexagonal and N-tier architectures · API gateway with Ocelot · EF Core and Dapper · PostgreSQL, MongoDB · NUnit + Moq, self-hosted integration tests |
Identity, storage & AI Keycloak with OAuth 2.0 · JWT bearer flows · SeaweedFS through the S3-compatible client · self-hosted LLM inference with Ollama · RAG pipelines with ChromaDB and embedding models · Copilot governance and AI spend controls |
40 pull requests across 32 projects I run or depend on. 6 merged so far, 30 still in review.
Merged
| Project | Change | PR | |
|---|---|---|---|
| dotnet/runtime | Fix CompareInfo.IsPrefix/IsSuffix with CompareOptions.IgnoreSymbols not ignoring leading/trailing symbols | #132397 |
|
| kubernetes-sigs/apiserver-network-proxy | Add connection_duration_seconds histogram for post-dial connection lifespan | #899 |
|
| StackExchange/StackExchange.Redis | Add NOMKSTREAM support to XADD | #3186 |
|
| DapperLib/DapperAOT | Fix false-positive DAP214 for {=XXX} literal-replacement syntax | #191 |
|
| nunit/nunit-console | Add AssemblyTargetFramework to IExtensionNode | #1867 |
|
| nunit/nunit-console | Fix --list-extensions showing wrong target framework for extensions | #1861 |
In review (30 open pull requests)
| Project | Change | PR | |
|---|---|---|---|
| moby/moby | Reuse per-host authorizers across a pull in the c8d resolver | #53457 |
|
| kubernetes/kube-openapi | Fix duplicate map keys when a type embeds two structs sharing a field | #631 |
|
| kubernetes-sigs/krew-index | Add safe-rollout plugin | #6213 |
|
| kubernetes/perf-tests | Add unit tests for clusterloader2/pkg/errors | #4261 |
|
| docker/cli | Normalize the registry server address to lowercase for credential lookup | #7184 |
|
| containerd/runwasi | Gate ctr image import --local by detected ctr version | #1177 |
|
| argoproj/argo-cd | Add ignoreDraft filter to ApplicationSet Pull Request generator | #29265 |
|
| argoproj/argo-rollouts | Stop degraded stable RS from permanently blocking subset DestinationRule switch | #4990 |
|
| argoproj/argo-workflows | Scope RemoveFromQueue to the calling controller | #16739 |
|
| open-policy-agent/opa | Make allow_net restrict file:// refs in JSON schemas | #9044 |
|
| spiffe/spire | Fix inaccurate expiring/outdated SVID sync metrics | #7230 |
|
| thanos-io/objstore | Support a custom GCS API endpoint through the endpoint config option | #270 |
|
| saltstack/salt | Fix file.managed omitting mode from changes when creating a file | #70084 |
|
| saltstack/salt | Fix module.run: positional arg for defaulted param raises 'multiple values' | #70083 |
|
| BurntSushi/ripgrep | Detect compressed files by magic number in search-zip, not just by extension | #3516 |
|
| BurntSushi/ripgrep | Fix the dangling backslash error for an escaped trailing space | #3515 |
|
| tokio-rs/tracing | Add an opt-in field value truncation wrapper to the subscriber | #3600 |
|
| dtolnay/cxx | Strip r# prefix from raw identifiers in generated C++ names | #1749 |
|
| rust-embedded/heapless | Add shift_remove family to IndexMap/IndexSet | #685 |
|
| dotnet/runtime | Return empty string instead of throwing when getpwuid_r fails unexpectedly | #132396 |
|
| dotnet/msbuild | Disable nullable analysis for net4x leg of multi-targeted projects | #14738 |
|
| StackExchange/StackExchange.Redis | Fix Sentinel connection leak and AbortOnConnectFail=false handling | #3187 |
|
| StackExchange/StackExchange.Redis | Make fallback discovery and keep-alive probes cluster-slot aware | #3185 |
|
| quartznet/quartznet | Add job type exclusion filter to trigger acquisition | #3282 |
|
| NLog/NLog | Change the DateLayoutRenderer default format to yyyy-MM-dd HH:mm:ss.ffff | #6252 |
|
| nsubstitute/NSubstitute | Document that Received.InOrder does not track property getters | #998 |
|
| dotnet-outdated/dotnet-outdated | Report packages whose source repository is archived or deleted | #781 |
|
| ansible/terraform-provider-aap | Remove aap_host from state on 404 during Read | #194 |
|
| traefik/traefik-helm-chart | Restore secretResourceNames for namespaced Role | #1972 |
|
| Azure/azure-powershell | Fix Get-AzSubscription silently ignoring mismatched -TenantId under MSI auth | #29994 |
|
kubectl-safe-rollout A kubectl plugin that tells you why a rollout failed or stalled. The cause classification is deterministic, there is no LLM in it, and it never writes to the cluster. Currently at v0.3.0, with the plugin submitted to krew-index. |
The workflows behind my CI/CD and FinOps posts, including the caching benchmark I ran 10 times on one runner. |
|
token-optimization Cuts token usage when you work with LLM coding agents. Setup is idempotent, so re-running it is safe. |
I write on LinkedIn about platform details that usually pass unchecked: how Azure DevOps resolves its three expression syntaxes, the compliance rules for self-hosted runners, what Copilot code review does and does not decide, and whether an Azure reservation discount is still applying to anything.