Performance & Best Practices
Your workbook is slow. Your users are complaining. Here's how to fix it.
The Performance Problem
WHY WORKBOOKS GET SLOW
─────────────────────────────────────────────────────────────────
Common Causes:
1. No filters → Querying ALL records (could be millions)
2. Too many joins → Each join multiplies complexity
3. Unused fields → Extra data transfer for nothing
4. Complex formulas → Calculated on every row
5. Large table views → Rendering 50,000 rows in browser
Result:
┌─────────────────────────────────────────────────────────────┐
│ │
│ ⏳ Loading... │
│ │
│ Your workbook is taking forever │
│ │
│ Users giving up → Using Excel instead → Data silos │
│ │
└─────────────────────────────────────────────────────────────┘
Fix 1: Filter Your Data (Most Important)
The #1 cause of slow workbooks: no date filter.
BEFORE vs AFTER
─────────────────────────────────────────────────────────────────
Before (SLOW):
┌─────────────────────────────────────────────────────────────┐
│ Dataset: All Invoices │
│ Filters: (none) │
│ Records: 847,000 │
│ Load time: 45 seconds │
└─────────────────────────────────────────────────────────────┘
After (FAST):
┌─────────────────────────────────────────────────────────────┐
│ Dataset: All Invoices │
│ Filters: Date is within "This Fiscal Year" │
│ Records: 12,400 │
│ Load time: 2 seconds │
└─────────────────────────────────────────────────────────────┘
Essential Filters by Report Type
| Report Type | Must-Have Filter |
|---|---|
| Revenue reports | Date range (This Year, Last 12 Months) |
| Open transactions | Status = Open/Pending |
| Customer analysis | Is Inactive = false |
| Inventory | Type = Inventory Item |
| AR aging | Amount Remaining > 0 |
Fix 2: Limit Your Joins
JOIN IMPACT
─────────────────────────────────────────────────────────────────
Joins: 1-5 → ✅ Fast (go for it)
Joins: 6-10 → ⚠️ Moderate (add more filters)
Joins: 10+ → 🔴 Slow (rethink your approach)
Example - Transaction Analysis:
❌ Too many joins (12):
Transaction
├── Customer
│ ├── Customer Category
│ └── Sales Rep
├── Transaction Line
│ ├── Item
│ │ ├── Item Category
│ │ └── Vendor
│ └── Location
├── Subsidiary
├── Department
└── Class
✅ Focused joins (5):
Transaction
├── Customer
├── Transaction Line
│ └── Item
└── Subsidiary
Ask yourself: Do I actually need all these fields?
Fix 3: Use the Right Root Record
RECORD TYPE PERFORMANCE
─────────────────────────────────────────────────────────────────
For transaction analysis:
❌ SLOW:
Transaction (standard)
+ Transaction Line (joined)
+ Transaction Accounting Line (joined)
= 3 separate record joins
✅ FAST:
Sales (Invoiced) or Sales (Ordered)
= Pre-joined analytical record (optimized)
The analytical records combine transaction + line + accounting
data into a single optimized structure.
When to Use Which
| Need | Use This |
|---|---|
| Invoice/revenue analysis | Sales (Invoiced) |
| Order/booking analysis | Sales (Ordered) |
| Multiple transaction types | Transaction (with type filter) |
| Customer master data | Customer |
| Item master data | Item |
Fix 4: Use Pivots Instead of Tables
TABLE vs PIVOT PERFORMANCE
─────────────────────────────────────────────────────────────────
Scenario: Show revenue by customer
❌ TABLE (SLOW):
┌──────────────┬──────────┬────────────────────────────────────┐
│ Customer │ Invoice │ Amount │
├──────────────┼──────────┼────────────────────────────────────┤
│ Acme Corp │ INV-0001 │ $1,200 │
│ Acme Corp │ INV-0002 │ $3,400 │
│ Acme Corp │ INV-0003 │ $2,100 │
│ ... 50,000 more rows ... │
└──────────────────────────────────────────────────────────────┘
Load time: 30+ seconds (browser struggles)
✅ PIVOT (FAST):
┌──────────────┬────────────────────────────────────────────────┐
│ Customer │ Total Revenue │
├──────────────┼────────────────────────────────────────────────┤
│ Acme Corp │ $156,000 │
│ TechStart │ $142,000 │
│ GlobalInc │ $98,000 │
│ ... 500 customers ... │
└──────────────────────────────────────────────────────────────┘
Load time: 2 seconds (aggregated server-side)
Why pivots are faster:
- Aggregation happens on the server
- Only summarized data sent to browser
- Fewer rows to render
Fix 5: Enable Dataset Caching
CACHING EXPLAINED
─────────────────────────────────────────────────────────────────
Without cache:
User opens workbook → Fresh query → Wait 10 seconds
User refreshes → Fresh query → Wait 10 seconds again
With cache:
User opens workbook → Cached data → Instant (< 1 second)
User refreshes → Cached data → Instant
(Cache refreshes every hour automatically)
Best for:
✓ Dashboards viewed frequently
✓ Reports that don't need real-time data
✓ Complex queries with many joins
Not ideal for:
✗ Real-time inventory monitoring
✗ Live order status
✗ Anything needing up-to-the-second accuracy
Common Slow Workbook Scenarios
Scenario 1: "My AR Aging Report Takes Forever"
DIAGNOSIS
─────────────────────────────────────────────────────────────────
Problem: Loading 5 years of invoices to show current aging
Current Setup:
├── Root: Transaction
├── Filters: Type = Invoice (but no date filter!)
├── Joins: Customer, Line, Item, Location, Department
└── Records: 340,000
Fix:
├── Add Filter: Amount Remaining > 0 (only unpaid)
├── Remove joins: Location, Department (not needed)
└── Records: 2,400
Result: 45 seconds → 3 seconds
Scenario 2: "Dashboard Portlets Keep Timing Out"
DIAGNOSIS
─────────────────────────────────────────────────────────────────
Problem: 6 portlets all hitting complex queries simultaneously
Current Setup:
├── Portlet 1: Revenue YTD (complex)
├── Portlet 2: Orders This Month (complex)
├── Portlet 3: AR Balance (complex)
├── Portlet 4: Top Customers (complex)
├── Portlet 5: Inventory Alerts (complex)
├── Portlet 6: Pipeline Value (complex)
└── Total load: 60+ seconds, timeouts
Fix:
├── Combine into fewer datasets with reusable data
├── Use pivots instead of tables
├── Add date filters to all
├── Consider: Does the CEO REALLY need all 6?
└── Total load: 8 seconds
Scenario 3: "Sales Report Works for Me, But Not for Reps"
DIAGNOSIS
─────────────────────────────────────────────────────────────────
Problem: Your role sees 5,000 records, but reps see 500,000
Root cause: Role-based restrictions not applied at dataset level
Current Setup (YOUR view):
├── Your role: See only your territory
├── Records: 5,000
└── Load time: 3 seconds
Sales Rep View:
├── Their role: See all (unrestricted)
├── Records: 500,000
└── Load time: timeout
Fix:
├── Add Subsidiary filter
├── Add Sales Rep filter
├── Or create separate dataset for reps
└── Load time: 3 seconds for everyone
Workbook Design Patterns
Pattern 1: The Executive Dashboard
STRUCTURE
─────────────────────────────────────────────────────────────────
One dataset, multiple visualizations:
┌─────────────────────────────────────────────────────────────┐
│ DATASET: "Executive Metrics - This Fiscal Year" │
│ Root: Sales (Invoiced) │
│ Filters: Date = This Fiscal Year │
└───────────────────────────┬─────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Tab 1: │ │ Tab 2: │ │ Tab 3: │
│ Summary │ │ Trend │ │ Details │
│ (Pivot) │ │ (Line Chart)│ │ (Table) │
└─────────────┘ └─────────────┘ └─────────────┘
Benefits:
✓ Single data fetch
✓ Consistent numbers across views
✓ Fast switching between tabs
Pattern 2: The Drill-Down Report
STRUCTURE
─────────────────────────────────────────────────────────────────
Start summarized, drill to details:
Tab 1: SUMMARY (Fast - shows aggregates)
┌─────────────────────────────────────────────────────────────┐
│ Region │ Revenue │ Orders │ Avg Order │
├───────────────┼────────────┼────────┼───────────────────────┤
│ North America │ $2.4M │ 1,240 │ $1,935 │
│ Europe │ $1.1M │ 890 │ $1,236 [Drill →]│
│ Asia Pacific │ $890K │ 720 │ $1,236 │
└─────────────────────────────────────────────────────────────┘
Tab 2: DETAIL (On demand - filtered by selection)
┌─────────────────────────────────────────────────────────────┐
│ Invoice # │ Customer │ Amount │ Date │
├────────────┼──────────────┼──────────┼──────────────────────┤
│ INV-4521 │ EU Corp │ $12,400 │ Dec 15 │
│ INV-4519 │ Berlin GmbH │ $8,900 │ Dec 14 │
│ (filtered to Europe only) │
└─────────────────────────────────────────────────────────────┘
Implementation:
- Tab 1: Pivot with Region, SUM(Amount), COUNT(*)
- Tab 2: Table with filter on Region
Pattern 3: The Reusable Dataset
STRUCTURE
─────────────────────────────────────────────────────────────────
One dataset, many workbooks:
┌─────────────────────────────┐
│ SHARED DATASET │
│ "Core Sales Data" │
│ - All invoices │
│ - This fiscal year │
│ - Standard fields │
└─────────────┬───────────────┘
│
┌─────────────────────┼─────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ CEO Dashboard │ │ Sales Report │ │ Finance AR │
│ (Pivot: KPIs) │ │ (Table: Deals) │ │ (Pivot: Aging) │
│ │ │ │ │ │
│ Owner: Admin │ │ Owner: Sales │ │ Owner: Finance │
└─────────────────┘ └─────────────────┘ └─────────────────┘
Benefits:
✓ Update dataset once, all workbooks benefit
✓ Consistent data across teams
✓ Reduced maintenance
✓ Shared caching
Sharing Best Practices
Who Should Own What
| Role | Owns | Shares With |
|---|---|---|
| NetSuite Admin | Core datasets, templates | All roles |
| Finance | AR/AP workbooks | Finance team |
| Sales Manager | Pipeline workbooks | Sales team |
| Operations | Inventory workbooks | Ops team |
Sharing Rules
SHARING FLOW
─────────────────────────────────────────────────────────────────
Share Dataset vs Share Workbook:
DATASET SHARING:
├── Others can use in their own workbooks
├── Others CANNOT edit your original
├── Good for: Reusable data sources
└── Who sees it: Based on their role permissions
WORKBOOK SHARING:
├── Others can view your visualizations
├── Others can Save As their own copy
├── Others CANNOT edit your original
└── Good for: Standard reports
Best Practice:
┌─────────────────────────────────────────────────────────────┐
│ 1. Create dataset → Share with team │
│ 2. Create workbook → Share with team │
│ 3. Team members: Save As to customize │
│ 4. Original stays protected │
└─────────────────────────────────────────────────────────────┘
Quick Performance Checklist
Before sharing your workbook, verify:
| Check | Why It Matters | How to Fix |
|---|---|---|
| ☐ Date filter exists? | #1 cause of slow | Add "This Year" or "Last 90 Days" |
| ☐ Under 10 joins? | Each join adds time | Remove unused record types |
| ☐ Using analytical record? | Pre-optimized | Switch to Sales (Invoiced/Ordered) |
| ☐ Pivot for summaries? | Aggregates on server | Replace tables with pivots |
| ☐ Only needed fields? | Less data to transfer | Remove unused columns |
| ☐ Tested with other roles? | Your data may be filtered | Ask a colleague to test |
Troubleshooting Guide
COMMON PROBLEMS & FIXES
─────────────────────────────────────────────────────────────────
PROBLEM: Workbook times out
FIX: Add date filter, reduce joins, use pivot
PROBLEM: Numbers don't match saved search
FIX: Check filters, check joins (duplicating rows?)
PROBLEM: Field I need isn't available
FIX: Check if record is joined, check role permissions
PROBLEM: Portlet shows "No data"
FIX: Check filters aren't too restrictive, check permissions
PROBLEM: Can't find my workbook
FIX: Check Analytics → Workbook tab, check it was saved
PROBLEM: Changes not saving
FIX: Check you're editing (not just viewing), check permissions
PROBLEM: Other users see different data
FIX: Expected! Role restrictions apply. Create role-specific filters.
The 5-Minute Workbook Audit
Run through this when workbook is slow:
QUICK AUDIT
─────────────────────────────────────────────────────────────────
1. FILTERS
Q: Is there a date filter?
A: No → Add one. Done.
2. RECORDS
Q: How many records in the dataset?
A: > 50,000 → Need more filters
3. JOINS
Q: How many record types joined?
A: > 10 → Remove unnecessary ones
4. VISUALIZATION
Q: Using table for 10K+ rows?
A: Yes → Switch to pivot
5. FORMULAS
Q: Complex formulas on every row?
A: Yes → Simplify or pre-calculate
Usually, #1 fixes the problem.
Summary: The Golden Rules
WORKBOOK PERFORMANCE RULES
─────────────────────────────────────────────────────────────────
Rule 1: ALWAYS add a date filter
(This Year, Last 90 Days, whatever makes sense)
Rule 2: Use analytical records for transaction reports
(Sales Invoiced, Sales Ordered)
Rule 3: Pivot tables > Table views for summaries
(Let the server do the work)
Rule 4: Keep joins under 10
(Ask: Do I really need this field?)
Rule 5: Test with other roles
(Your 5K records might be their 500K)
Quick Links
| Need Help With | Go To |
|---|---|
| Building datasets | Datasets → |
| Creating visualizations | Tables, Pivots & Charts → |
| Writing formulas | Formula Fields → |