So we finally pulled the trigger and migrated our finance team’s remote access off the legacy VPN and onto Netskope’s ZTNA. Three hundred users, all with a pathological need to access sensitive data from questionable coffee shop Wi-Fi. The promise was smoother than a fresh jar of Skippy, but the reality, as always, had some crunchy bits.
The big win is the user experience. Once it’s working, it’s invisible—which is the whole point. But getting there? Let’s just say the “zero” in zero trust also applies to the number of times our initial app profiling was correct. We assumed all our legacy internal web apps would just be discovered and neatly categorized. Netskope’s engine missed a few critical, custom-built portals. The result? Day one tickets from analysts who couldn’t run reports. The lesson: manually profile and test every single application, even the ones you think are “standard.” Your “Oracle E-Business Suite” might be a snowflake of customizations that looks like a strange cat video to the classifier.
The other fun pitfall was with clientless access for contractors. The setup for web apps is straightforward, but we had a handful of fat-client applications that needed TCP forwarding. The configuration there is… finicky. If your app doesn’t play nice with explicit proxy settings or you have dependencies on specific local ports, prepare for some surgical-level troubleshooting. We ended up creating more granular policies than we’d anticipated, almost segmenting by user *and* app, which felt like overkill but was necessary to keep things running without a dozen exceptions.
Performance-wise, it’s been solid after tuning. The initial latency complaints came from users whose traffic was being backhauled to a data center on the other side of the continent. The geo-location of Netskope’s POPs matters more than the sales deck lets on. We adjusted the steering policies to favor proximity over other metrics, and the grumbling stopped. Don’t just accept the default routing.
All in all, it’s a powerful shift, but it’s not a set-it-and-forget-it magic box. You’re trading VPN headaches for a different set of configuration and profiling headaches. The trade-off is worth it for the security model, but go in with your eyes open. Test more than you think you need to, and assume your first policy set is wrong.
just sayin'
Data over dogma.
Oof, the app profiling struggle is real. We had a similar "assumed standard" moment with a vendor portal that was actually a heavily modified Joomla instance. Netskope flagged it as generic web traffic, which was... less than secure.
Your point about manual testing is the key. It's tedious, but building that internal catalog of "what it actually is vs. what the tool thinks it is" saves so many day-one fires. Did you find the false positives were also an issue, or was it mostly things being missed?
Keep it civil, keep it real.
Absolutely, false positives were a significant hurdle for us as well. The profiling engine would occasionally flag a legitimate, modern SaaS tool as "Potential Shadow IT" or assign a wildly inaccurate risk score. This created unnecessary friction with the security team during the rollout.
Our workaround was to lean heavily on the manual override and exception list features early on. It felt like admitting defeat, but it was the only way to stabilize the user experience while we refined the underlying policies. The real lesson was that the initial deployment isn't about perfect categorization, it's about building that stable baseline you mentioned. Once the noise is reduced, then you can start tightening the screws.
Every dollar counts.
Your point about the manual overrides and exceptions being a tactical necessity is correct, but it introduces a long-term contractual and operational risk that often gets overlooked. Those exceptions become technical debt, embedded in your configuration but absent from the master service agreement or ongoing support SLA.
Vendors love this state because it locks you in. When renewal comes, the conversation shifts from feature parity to the immense "cost of re-profiling" your entire environment if you were to switch. You've essentially custom-built your own policy cage. The procurement lesson is to negotiate audit rights for exception lists and require the vendor to provide a structured, exportable record of all manual categorizations as part of the regular service review. This turns a tactical workaround into a governed asset.
Oh wow, that's a perspective I hadn't considered at all. Thanks for explaining it!
>Those exceptions become technical debt
This makes so much sense. I was just thinking about making things work, not about getting locked in later on. Asking for exportable records during procurement is a really smart move.
How do you even start that conversation with a vendor? Is it something you'd bring up early, or wait until you're negotiating the contract details?
"Stable baseline" is an optimistic way to describe a configuration full of manual overrides. That friction with your security team you mentioned? It doesn't magically go away. You've just traded immediate deployment fires for a permanent, low-grade policy management war.
Every exception you baked in becomes a future argument. When the security team eventually wants to lock down a SaaS category, you'll have a dozen "special" instances that break the rule, each with its own forgotten justification from the rollout chaos. The technical debt isn't just in the config, it's in the institutional memory you're betting won't fade.
You're right that you need the overrides to stop the bleeding. But calling it a baseline implies you'll clean it up later. In my experience, "later" is when the person who built the exceptions list has left the company.
prove it to me
You're touching on something that's been worrying me as I plan our own rollout. That institutional memory point is huge. We tried to solve it in a different project by creating a simple "policy justification" field in our internal wiki for every override, with a required review date.
It turned into another piece of admin that nobody updated. The person who set the date usually left before it came up. So the debt just sat there, documented but just as forgotten.
Is there a process you've seen that actually works for keeping that context alive, or is it fundamentally a people problem that tech can't fix?
Yeah, the "institutional memory" part is the real killer. You can document all you want in a wiki or a CMDB, but if the business context behind an exception isn't attached to the policy itself, it's lost.
One thing that's helped us a bit is treating overrides like a mini-change ticket from day one. We force a short description field in the tool itself when creating an exception, something like "Allow legacy auth for AppX due to Vendor Y's API limitation until Q4 upgrade." It's still brittle, but at least the "why" lives with the config. When the next security review happens, that note is right there, even if the original engineer is gone.
Of course, that just turns the problem into one of policy clutter instead of lost memory. No easy wins here.
ship it
Ugh, the clientless fat-client struggle. We ran into that with a legacy actuarial modeling tool. The TCP forwarding worked, but the latency from the nearest Netskope PoE made it unusable for the actuaries. Had to get a special exception to run a tiny terminal server in a VPC just for that app, which kind of defeated the "clientless" dream.
The app profiling pain is so relatable. We learned the hard way that "manually test every single application" also means testing every *version* of access. The internal portal worked fine, but the mobile view for tablets? Blocked.
Yeah, forcing a description field directly in the tool sounds like the best you can do. But then how do you handle it when the reason for the exception changes, or when the "until Q4 upgrade" date comes and goes? Does your team have a process to actually review those notes, or do they just become permanent, stale justifications?
That's exactly the problem - stale justifications become the new norm. We tried a quarterly review process, but it was overwhelming.
What worked better was tagging exceptions with the Jira ticket ID that *created* them. Our CI/CD pipeline then runs a script that checks if those tickets are still open. If a ticket is closed for more than, say, 90 days, the script flags the linked policy for manual review. It's not perfect, but it creates a forcing function tied to the actual work.
It turns a vague "we should review these" into a specific alert for the security team. The notes still get stale, but at least there's a system to surface them.
Clean code, happy life