Designing systems is a craft that is becoming attractive to more and more people. We should all be aiming to build solutions that balance technical excellence with the harsh realities of business needs. The most elegant code can fall flat if it doesn’t fit the quirks and complexities of the real world.
Across the industry, ‘architecting’ has become a verb that we all like to throw around. Frameworks such as Well-Architected have helped many of us flex our design muscles. But as Salesforce’s out-of-the-box power grows, the real magic often happens inside Lightning Web Components (LWCs).
With GenAI tools now accelerating how quickly we learn and build, it’s easier than ever to dive in. But speed and willpower aren’t going to cut it. Having a well-thought-out framework to guide your approach is going to be what sets good solutions to great solutions.
After a few years of building LWCs, I found myself wishing for a simple, memorable checklist to make sure I was covering the core bases from the first sketch to the final sign-off. I started jotting down some principles I have found success with, and the PICKLES framework was born! This is a practical guide that I hope others will keep coming back to and will keep being useful – whether you’re a developer, an architect, or somewhere in between.
The PICKLES Framework
Aptly named – and yes, a little tongue in cheek – PICKLES is designed to be your go-to reference for designing robust, well-thought-out, and considered LWCs, no matter the size. Let me break down what each letter stands for.

P – Prototype
Prototyping helps catch design flaws earlier, saving time and effort for you, your developers, and your users.
What This Means
Sketching a high-level POC (Proof of Concept) of the application’s components, wireframe, and simulating, with mock data to validate ideas between systems if needed, or seeing user experiences first hand rather than conceptually!
How and Tips
- Mock Data generated by a GenAI can help quickly get a ‘close’ set of data to play with while you’re gathering valuable feedback. Check out Dummy Data using GenAI for Testing and Validation.
- Lucid or a diagramming tool (or sketching!) is a great way to conceptualise ideas and work with stakeholders. Check out Flux Academy’s 20 wireframe examples.
- Split the component into ‘separations of concerns,’ which is a design principle we can use in our LWCs to break them up into smaller functional pieces.
Example

I – Integrate
When building LWCs, you’ll need to decide how your component interacts with data in the system.
What This Means
Every component will work with data in some shape or form, whether it be hooking into the Lightning Data Service cache, retrieving via Apex or API-driven data!
Establishing exactly how and where the component will gather and send the data will fundamentally drive the build and security settings.
How and Tips
- Cache data when appropriate, while Lightning Data Service (LDS) does this automatically. Apex and API don’t. Think about local storage or in-memory caching!
- Handle errors gracefully with toast messages informing the user clearly what is happening.
- When getting data, don’t forget about loading spinners and preventing the user from retriggering data operations while it’s already in progress.
- Utilize LDS when working directly with records, as it reduces the amount of DML calls.
- Think whether the data interacts with a single object or related objects.
Common Pitfalls
- Relying solely on Apex for CRUD operations when LDS is appropriate.
- Not handling errors or loading states leads to a janky user experience and causes more real-time dependent bugs.
- Forgetting to consider FLS and CRUD permissions when using Apex.
Examples

C – Composition
How are LWCs exposed within one another are structured hierarchically.
What This Means
Composition is about how you structure your LWCs – how they nest, communicate, and share responsibilities for the overall ‘task’. Good and appropriate composition leads to a reusable and maintainable component, while driving the events and communication patterns. For example, will the information from one component to another pass to a ‘sibling,’ or will a parent house the different elements of a component?
How and Tips
- Use public properties (
@api
) for parent-to-child data flows. - Create custom events based on their purpose: standard events for simple data passing, custom for complex and custom interactions.
- Deciding to use the sibling to be responsible for its data submission can be less complex and cleaner than pushing data and events unnecessarily up to a parent.
- Try to avoid unnecessarily deep nesting. The goal is to have a maintainable LWC that can extend over time. Don’t jump the gun!
Common Pitfalls
- Over-nesting components. Making every functionality a separate component makes the hierarchy harder to manage.
- Don’t use an event for everything – sometimes a property to hold data is enough.
- Not understanding lifecycle hooks and using them incorrectly causes a lot of repeated rendering and memory leaks –
connectedCallback()
for setup,renderedCallback()
for updates, anddisconnectedCallback()
for cleanup.
Examples
1. Parent-Managed Composition Pattern

- What It Is: Data and state are managed by the parent component and passed down to children via
@api
properties. - When to Use It: When components need to share data and the parent needs to coordinate between children.
- Benefits: Centralized state management, clear data flow, easier debugging.
- Drawbacks: Can lead to “prop drilling” for deeply nested components – parent becomes complex with many concerns.
Composition Best Practices:
- Aim for Shallow Hierarchies: Deep nesting creates complex dependencies and makes reuse difficult.
- Choose the Right Communication Pattern: Don’t overuse events for everything.
- Clean Up in disconnectedCallback() : Prevent memory leaks by unsubscribing from LMS.
- Keep Components Focused: Each component should have a single responsibility.
- Balance Granularity: Too many small components can be as problematic as too few large ones.
2. Sibling Communication Pattern

- What It Is: Components communicate across complex DOM branches via Lightning Message Service (LMS) without involving the parent.
- When to Use It: When components are loosely coupled or when you need communication between components that aren’t in a direct parent-child relationship.
- Benefits: Decoupled components, simpler parent component, more flexible component reuse.
- Drawbacks: More complex to debug, potential for message spaghetti, need to manage subscriptions.
Composition Best Practices:
- Aim for Shallow Hierarchies: Deep nesting creates complex dependencies and makes reuse difficult.
- Choose the Right Communication Pattern: Don’t overuse events for everything.
- Clean Up in
disconnectedCallback()
: Prevent memory leaks by unsubscribing from LMS. - Keep Components Focused: Each component should have a single responsibility.
- Balance Granularity: Too many small components can be as problematic as too few large ones.
K – Kinetics
Referring to the movement and interactivity within your LWC.
What This Means
How the component(s) respond to user actions and internal events. Things like capturing user input, responding to clicks, managing how the event bubbles up through the hierarchy and how the data flows upwards.
How and Tips
- Think carefully about how you bubble and compose events on user input. Does a field change need to bubble upwards to the highest component?
- Put input events on a timeout (e.g. typing in a search box to query the database) to avoid a query for every key-up event and spamming the database (this is also known as “debouncing”).
- Capture and validate user input before acting on it.
- Disable inputs programmatically (and appropriately!) when changing the input will be inconvenient to the current flow.
Common Pitfalls
- Not debouncing rapid-fire events (such as a user typing) can lead to huge performance issues and excessive API call-out costs.
- Overusing the same events across inputs can make it harder to debug.
- Failing to clean up event listeners to avoid reprocessing events unnecessarily.
Example

L – Libraries
External tools and APIs that Salesforce provides and the masses of pre-created JavaScript libraries.
What This Means
Libraries are tools and APIs provided by Salesforce and others that help you build robust, secure, and feature-rich LWCs! Using Salesforce APIs grant you access to powerful features that aren’t available through standard configuration –such as the UI API for programmatic navigation and the Workspace API for customizing the user interface. These APIs provide a secure, high-performance way to interact with the platform and will save you time.
Salesforce utility libraries include:
- The Navigation API, to navigate the user between pages and records
- The UI API, for retrieving metadata and data respecting CRUD
- Base Components, for pre-build UI elements
How and Tips
- Make a list of pre-existing libraries you can use while building your components.
- Use base components instead of writing custom code saves a lot of time and ensures your component stays up to date with Salesforce’s latest features and security updates.
- Use the Toast Library for notifications.
- Check Locker Service compatibility before committing to third-party libraries (see the “P – Prototype” section above).
Common Pitfalls
- Reinventing the wheel for things that already exist as LWC base components.
- Committing to third-party libraries that don’t work in Locker Service.
- Not keeping up with the ever-increasing Salesforce-provided utilities!
Examples
By navigating to the Salesforce Lightning Component Library, you’ll find a vast, filterable list of assets that you can use – ranging from front-end to API usage.

Lightning Web Components Recipes has a front-end interface for some excellent LWC examples.
E – Execution
How the component runs in relation to performance and lifecycle.
What This Means
Execution is about ensuring the LWC loads quickly, updates smoothly, and doesn’t waste resources. It’s about creating components that are responsive, efficient, and scalable. Good execution means the component is quick and responsive in a real-world scenario, including both slow and fast internet connections.
How and Tips
- Focus on what data will be loaded and when, at each lifecycle hook stage.
- Implement lazy loading for large volumes of data, such as query results or components that aren’t needed immediately.
- Be aware that each property update will re-render the LWC. Consider assigning properties on a button click rather than on state change.
- Monitor performance with browser dev tools (this is your best friend!).
Common Pitfalls
- Triggering too many re-renders of your component by updating properties unnecessarily – consider debouncing again.
- Doing heavy processing in main components synchronously, causing significant UI lag for the user.
- Not cleaning up properties and resources in lifecycle hooks.
Examples

S – Security
Who can see what – and when.
What This Means
LWC runs in the user context, ensuring that users only see and interact with the data and records they’re authorized to do so, while respecting Salesforce’s security model (FLS, CRUD, Sharing). It’s about more than just hiding buttons – it’s about safeguarding data and business processes.
How and Tips
- Check custom user permissions for certain parts of the component to hide or show functionality and sensitive data for managers or regular users.
- Respect FLS/CRUD in Apex and UI. Unless the component should specifically elevate isolated fields and access, ensure Apex consumes basic.
- Use LWC metadata to control where the component is allowed to be used across the org, and use Lightning App Visibility filters to further show or hide it.
- Avoid exposing sensitive data in client-side code, as it could be accessed in a community by a malicious user who can retrieve the information.
Common Pitfalls
- Hardcoding permissions or assuming every user should have access to the LWC and all all its functionality.
- Failing to specifically check for CRUD access when running queries with the without sharing access level when the LWC requires Apex.
- Checking for string injections for direct queries.
- Exposing sensitive information (client secret, unnecessary user data in payloads) which can be inspected by users.
Examples
By contextualizing the user running the component, you can perform additional checks, such as restricting certain functionality by hiding entire sections, while constantly checking and validating the performed actions.

Summary
I encourage you to print this guide (or bookmark it), and the next time you design an LWC, write PICKLES next to whatever you’re using to design. Run through each letter as you brainstorm. Doing so will steer you toward more reliable, maintainable components, a smoother build and design process, and much happier end-users.
Feedback is always welcomed – feel free to suggest improvements or share your battle-scars! Drop a comment below, or reach out to me on LinkedIn.