Winter '26 Platform Developer Updates: What You Actually Need to Know
Introduction
Another Release, More Features to Learn
So the Salesforce Winter ’26 release is now generally available, many developers are revisiting the platform updates as part of their certification maintenance. I get it - nobody wants to spend hours reading release notes. But here's the thing: this release actually has some useful stuff. I went through all the developer updates and honestly, most of them will probably come up in your actual work. Let me break it down so you can understand what changed and why it matters.
Some features may require specific org settings, pilots, or phased rollout depending on edition and cloud.
Handling Big Files Without Breaking Everything
The Problem We Had
If you've ever tried to upload or download large files through Apex, you know the pain. You hit the heap limit at like 6MB and then everything crashes. It's been a constant headache when integrating with external systems that need to transfer PDFs, images, or any kind of binary data.
What Changed
Salesforce introduced a more scalable pattern for handling large files when using External Services. Instead of loading everything directly into the Apex heap (which is tiny), they now use pointers to ContentDocument IDs. Basically, the file goes straight into Salesforce's file storage, and you just work with a reference to it.
What You Can Do Now:
Upload and download binary files up to 16 MB
Transfer binary files without hitting Apex heap limits during file transfer operations
Keep files accessible in Salesforce after transfer (good for auditing)
Integrate with external document management systems more reliably
Real Talk:
This is great if you're just moving files around - like uploading invoices to a third-party storage system or pulling documents from an external API. But if you need to actually parse or manipulate the file contents in Apex, you're still limited. You'd have to process it in smaller chunks. For simple transfers though? This solves a massive problem.
When to Use This:
Perfect for integrations where you're transferring files but don't need to transform them in Apex. If you're building a connector to a digital asset management system, an invoicing platform, or any external storage - this is your solution.
Access Modifiers Are Now Required (Yes, Really)
What's New
Starting with API version 65.0, Salesforce enforces stricter compilation rules for access modifiers on abstract and override methods. This applies when upgrading classes to API version 65.0 or higher. You MUST explicitly declare them as protected, public, or global. No more leaving them out or using private (which never made sense anyway since sub-classes couldn't access them).
Why This Matters
Before this, you could write sloppy code that technically compiled but didn't really work right. Now Salesforce forces you to be explicit, which actually makes your code clearer. If you try to skip the access modifier or use an unsupported one, you'll get a compilation error.
Example - The Right Way:
// Abstract class
public with sharing abstract class Shape {
public abstract Double calculateArea();
}
// Extend the class and override the method
public with sharing class Square extends Shape {
public Double side;
public Square(Double s) {
this.side = s;
}
public override Double calculateArea() {
return side * side;
}
}
What You Need to Do:
Before you upgrade any classes to API version 65.0 or later, review your abstract and override methods. Add the explicit access modifiers. It's a quick fix, but if you skip it, your code won't compile. Pro tip: do a find/replace in your codebase for "abstract" and "override" to catch them all at once.
Running Third-Party Scripts Without Security Blocking Them
The Background
Lightning Web Security (LWS) and Lightning Locker are Salesforce's security layers that protect your org by isolating components and blocking access to the global namespace. That's great for security, but it also breaks a lot of legitimate third-party libraries that need global access to work properly - things like jQuery, D3, analytics tools, etc.
The Solution: LWS Trusted Mode
Now you can mark a component as "trusted" to relax certain Lightning Web Security and Locker restrictions. This lets you run third-party scripts that require global context access. It's basically an escape hatch for when you have business-critical libraries that don't play nice with Salesforce's security architecture.
What This Enables:
Expanded access to browser APIs that are normally restricted by LWS. Trusted mode should only be enabled for vetted, business-critical libraries and follows Salesforce security governance requirements
Full DOM Manipulation: Access and modify any part of the DOM, including Salesforce-managed elements and shadow DOM
Better Performance: Skip the LWS layer for performance-heavy operations
Library Compatibility: Run libraries like jQuery, D3, or custom analytics scripts that rely on global state
Important Warning:
Only enable trusted mode for libraries you completely trust and have vetted. When you bypass security restrictions, you're opening up potential attack surfaces. If the script is compromised or malicious, it can do real damage. Follow your org's governance process and Salesforce security guidelines before using this in production.
When to Use This:
Perfect for integrating essential third-party tools - advanced charts and graphs, marketing analytics, specialized UI libraries, or any vetted script that your business depends on. Not for random npm packages you found online.
New and Updated Lightning Web Component Modules
What's New in LWC
Salesforce keeps expanding what you can do with Lightning Web Components. This release brings some new modules and updates to existing ones. Here's what you need to know:
New Modules
lightning/graphql
This is the replacement for the deprecated lightning/uiGraphQLApi module. Use it to fetch data with the GraphQL API for UI API-enabled objects. It respects object-level and field-level security for the current user, which is great for building secure interfaces.
Supports optional fields and dynamic query construction
Recommended for all new GraphQL-based data fetching
NOT supported for Mobile Offline (use the old uiGraphQLApi for that)
When to use it:
When you need flexible data queries in your LWC components. GraphQL is great for fetching exactly the fields you need without over-fetching data. Just remember - if you're building for mobile offline, stick with the old module for now.
lightning/omnistudioPubsub
Enables your custom components to communicate with FlexCards or OmniScripts using a publish-subscribe mechanism. This is specifically for OmniStudio integrations.
When to use it:
If you're working with OmniStudio and need your custom LWC to interact with FlexCards or OmniScripts. It's a pretty niche use case, but if you're in that ecosystem, it's essential for component communication.
Updated Modules
lightning/conversationToolkitApi
They added a new method to this module:
inactivateConversation(recordId) - Inactivates a conversation record by ID. Returns a promise that resolves to true or rejects with an error.
When to use it:
If you're building custom messaging or chat interfaces in Salesforce. This gives you programmatic control over conversation lifecycle.
lightning/uiGraphQLApi (DEPRECATED)
This module is officially deprecated - the wire adapter, refreshGraphQL() function, everything. Salesforce isn't adding new features to it anymore.
Action Required:
Migrate to lightning/graphql for new development. If you have existing code using uiGraphQLApi, start planning the migration. The only exception is Mobile Offline scenarios - keep using the old module for those until Salesforce adds offline support to the new one.
Using Lightning Web Components in Screen Flows
What This Unlocks
Screen flows have always been great for guiding users through processes, but they've been limited in how they interact with the browser. Now you can use Lightning Web Component (LWC) local actions in screen flows to perform limited client-side UI operations directly in the user’s browser without requiring a server roundtrip.
Examples of What You Can Do:
Display a custom toast message after form submission
Navigate to a specific record page automatically
Update UI elements dynamically
Trigger browser-side validations or calculations
Show/hide sections based on user interactions
Why This Matters:
Local actions are fast because they run in the browser - no server roundtrip needed. They're also more efficient since they don't consume server resources or count against governor limits. For simple UI interactions or navigation, this is way better than making an Apex call.
How to Set It Up:
1. Create a Lightning Web Component in your SFDX project
2. Add the lightning__FlowAction target in your component's config file
3. Define the properties you want to expose to Flow Builder
4. Deploy the component to your org
5. In Flow Builder, add an Action element and select your component
Quick Example - Toast Message Component:
Here's a simple component that shows a toast notification in a flow:
<!-- Component Config (meta.xml) -->
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>65.0</apiVersion>
<isExposed>true</isExposed>
<targets>
<target>lightning__FlowAction</target>
</targets>
<targetConfigs>
<targetConfig targets="lightning__FlowAction">
<property name="toastTitle" type="String" label="Toast title to display" />
<property name="toastMessage" type="String" label="Toast message to display" />
</targetConfig>
</targetConfigs>
</LightningComponentBundle>
// JavaScript (component.js)
import { api, LightningElement } from 'lwc';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
export default class ShowToastExampleComponent extends LightningElement {
@api toastTitle;
@api toastMessage;
@api invoke() {
this.dispatchEvent(new ShowToastEvent({
title: this.toastTitle,
message: this.toastMessage,
}));
}
}
When to Use Local Actions:
Use them for anything that doesn't need server data - UI feedback, navigation, client-side calculations, form resets. For operations that require querying or updating Salesforce records, stick with server-side actions.
Testing Apex and Flows Together
The Problem We Had
Until now, Apex tests and flow tests were completely separate. You'd run Apex tests through one interface, flow tests through another, and manually check both sets of results. It was annoying and easy to forget one or the other, especially before deployments.
What's New
As part of the Winter ’26 platform updates, Salesforce introduced new APIs to unify Apex and Flow testing:
Test Discovery API: Gives you a single view of all tests in your org - both Apex and automated flow tests. No more checking multiple places.
Test Runner API (Updated): Execute both Apex and flow tests in the same run. One API call, all your tests running together.
How It Works:
1. Call Test Discovery API to see all available tests (Apex classes with @isTest and autolaunched flow tests)
2. Filter or select which tests you want to run
3. Use Test Runner API to execute them all in one go
4. Get a unified test run ID that you can poll for results
5. See all test outcomes in one place
Setup UI Option:
Not into APIs? You can now run both Apex and flow tests directly from Setup. Navigate to the test management section, select your tests, and run them together declaratively. Same unified experience, no code required.
Why This Is Huge:
Simplified CI/CD: One test run instead of two separate processe
Better visibility: See your entire test suite at a glance
Faster feedback: Catch issues in both Apex and flows simultaneously
Easier deployments: Actually run all tests before going to prod
Less context switching: Stay in one workflow instead of jumping between tools
Integration Example:
If you're using Jenkins, GitHub Actions, or any CI/CD tool, you can now add a single step that runs all tests. Before this, you had to set up separate jobs or scripts for Apex and flow tests. Now it's one API call that handles everything.
Things to Watch:
Running all tests can take time - plan your pipeline timing accordingly
Organize tests with naming conventions so you can run relevant subsets
If you haven't been writing flow tests, now's a good time to start
Keep an eye on Tooling API limits if you're running tests frequently
You'll need to refactor existing test processes to use the unified approach
Finally
My Take on This Release
Winter '26 is a solid update for platform developers. The big file transfer fix solves a real pain point that's been around forever. The access modifier requirement might seem annoying, but it actually makes code better. LWS Trusted Mode opens up possibilities for third-party integrations that were difficult before. The LWC module updates modernize the development experience, especially with GraphQL support. Local actions in flows are genuinely useful for building better user experiences. And the unified testing? That's just common sense that should have existed years ago.
What You Should Focus On:
If you work with external integrations, the large file transfer feature is worth implementing immediately
Update your abstract/override methods before upgrading to API 65.0 - it's a quick fix that prevents headaches
Start migrating from uiGraphQLApi to the new graphql module in your LWC components
If you build flows, experiment with local actions for better UX
Definitely set up unified testing in your CI/CD pipeline - it'll save you time on every deployment
For Certification Maintenance:
All of these topics are fair game for the maintenance badge questions. Make sure you understand not just what changed, but why it matters and when you'd use each feature. Salesforce loves asking scenario-based questions, so think about real-world use cases for each update.
Good luck with your certification maintenance, and the best way to understand these updates is to try them in a sandbox and evaluate how they fit your development workflows. You'll learn way more by actually using them than by just reading about them.

