Making your Trading Experience on Dhan Web - 10X Faster than ever | From Market Tick to Browser How We Optimised Dhan Web

Dear Investors & Traders,

At Dhan, we own most of our technology stack and infrastructure - which helps us provide our users - Super Traders & Long-Term Investors an incredibly fast and efficient trading experience, and helps to ensure we maintain an edge for our users.

Nope - this is not or never been a market standard for the Broking Industry. Most platforms in India do not have their own platforms, they use third party core OMS & RMS trading engines, use many third party vendor solutions or data for their front-office and back-office, data, market feeds and likes.

Dhan Web - Faster than ever!

Investing and building Tech Stack from Scratch

We own our own core proprietary trading systems, built from scratch with DEXT, our own infrastructure across multiple locations, our own front-end platforms, own market feeds that help us ensure speed & accuracy behind every tick, to processing our own traders and showcasing it in our backoffice Journal.

At Dhan we have competed on price, but we do care a lot to ensure we deliver an extra-ordinary experience and value to our users. We have invested deeply over the past few years, millions of dollars into our technology & infrastructure capabilities. We possibly are only trading platforms who have their own GPUs for advanced AI capabilities.

To make it simple, we do everything to optimize the journey of a market tick - from the exchange, through our market-data infrastructure, to the trader. But that journey does not end when the data reaches our servers or even the customer’s device. It ends only when the latest price is rendered on a watchlist, chart, position or order window - and the trader can act on it.

Our backend systems, including DEXT and our proprietary market-data platform, are engineered for speed. This led us to ask a simple question:

If our backend systems are fast, should the browser ever become the reason a trader sees or acts on information, can it be delivered faster than ever?

That question started a comprehensive performance optimization of Dhan Web. The objective was not simply to achieve a better Lighthouse score. We wanted Dhan Web to load faster, remain responsive during periods of high market activity, switch smoothly between trading screens and continue performing consistently throughout a full trading session.

A Trading Platform is not a Conventional Website

A conventional website typically retrieves content, renders a page and waits for the next user interaction. A web-based trading platform behaves very differently.

Even when the trader is not clicking anything, the application continues to receive and process:

  • Live market prices and market-depth updates

  • Order-status changes

  • Position and P&L updates

  • Watchlist changes

  • Alerts and notifications

  • Chart and indicator updates

  • Connectivity events

Many of these events can arrive simultaneously, particularly during market opening or periods of high volatility.

Dhan Web is built on Angular and consists of approximately 300+ frontend units: 200+ components, 50+ services, 15+ pipes and 15+ directives. These units collectively manage watchlists, charts, orders, positions, holdings, funds, market information and several other trading workflows.

This scale meant that optimising Dhan Web required more than compressing a few files. We needed to examine how the application loaded, detected changes, processed live events and retained state during navigation.

And we have to manage this for nearly 600,000+ daily active traders, and at times nearly 400,000+ concurrent users during market hours.

Measuring before Optimising

We began by establishing a performance baseline across application startup, bundle composition, main-thread work and visual stability. The audit showed that the browser was downloading, parsing and executing more code than necessary before a trader reached the core experience.

We focused our optimisation efforts on the following areas: reducing the amount of JavaScript loaded during startup; loading feature-specific libraries only when needed; removing legacy scripts that blocked initial loading; limiting unnecessary change detection; eliminating unused dependencies; preventing expensive screens and resources from being recreated during navigation; fixing font preloading; reducing avoidable object allocations caused by frequently changing market values; and removing global styles irrelevant to the initial screen.

This gave us a clear direction - reduce what the browser downloads, reduce what it parses and executes, and make interface updates more intentional.

Loading only what the Trader usually needs

The first major change was to reduce the amount of code required to start Dhan Web. Over time, a large application naturally accumulates features and dependencies. If they remain part of the initial bundle, every customer must download and parse them - even when those features are not used during that session.

We audited the initial dependency graph and separated feature-specific functionality from the application’s startup path. Large libraries and modules used for data grids, animation, reporting, spreadsheet generation and secondary visualisation were moved behind lazy-loaded routes or dynamic imports.

To achieve this, we moved the data-grid library and other feature-specific capabilities behind lazy-loaded routes or dynamic imports, removed unnecessary locale data, lazy-loaded the funds workflow and separated major market, order, position, holding and IPO modules. We also expanded the number of lazy-loaded chunks from 19 to 29 so that more capabilities are delivered only when required.

This allowed the application to download the core trading experience first and retrieve secondary capabilities only when the customer requested them.

After this optimization, the initial bundle transfer was 1.08 MB, the uncompressed initial bundle was 6.38 MB, and the main JavaScript transfer was 999 KB. The main JavaScript bundle was 5.69 MB, while the application used 29 lazy-loaded chunks to retrieve more capabilities only when needed.

The important outcome was not merely a smaller download. With less JavaScript to parse during startup, the browser performed less CPU work and faced lower main-thread pressure.

Creating a Backend for Frontend

Reducing the size and execution cost of the frontend was only one part of the optimisation. We also reviewed how Dhan Web interacted with our backend services.

Previously, the frontend had to call multiple APIs to construct certain screens. It had to wait for different responses, combine the data and transform it into the format required by the interface.

This made the browser responsible for both rendering the customer experience and understanding how data from different backend services related to each other. Multiple API calls also introduced additional network round trips and made loading dependent on the slowest response.

This created additional network round trips and forced the frontend to coordinate multiple asynchronous responses. A delay or failure in one API could hold up the complete screen, while aggregation, transformation, error handling and retries also had to be managed in the browser. Changes in backend services could therefore require corresponding frontend changes.

To simplify this flow, we created a Backend for Frontend, or BFF, specifically for Dhan Web. The BFF provides APIs designed around frontend journeys and screen requirements rather than exposing the browser directly to multiple underlying services.

The BFF collects the required information from relevant backend systems, prepares it in the format needed by the interface and returns a frontend-specific response.

Previously: Browser → Multiple backend APIs → Frontend aggregation → Screen rendering

Now: Browser → Frontend-specific API → Backend aggregation → Screen rendering

By moving aggregation and orchestration closer to our backend systems, we reduced the number of calls made by the browser, simplified frontend data handling and reduced dependencies between frontend components and individual backend services.

The objective was not to combine every API into one large response. Each BFF API was designed around a specific customer journey, allowing different screens to retain their own data and freshness requirements while keeping the contracts consumed by the frontend simple and purpose-built.

The browser should not need to understand the topology of our backend systems to render a trading screen.

Optimising frontend dependencies and startup scripts

Large applications naturally accumulate dependencies as they evolve. We optimised how Dhan Web uses them across runtime and development paths, favouring native browser capabilities and smaller purpose-built implementations where appropriate.

The application now uses native browser APIs for relevant interface behaviour, native JavaScript for suitable utility operations, navigator.onLine for connectivity checks and focused local implementations for tasks such as time formatting.

We also streamlined the global scripts path so that unrelated legacy code no longer delays application startup. The browser now begins the critical trading experience with a lighter dependency footprint and less blocking work on the main thread.

Zoneless Angular and Signals for Live Market Data

Reducing bundle size improved startup performance, but it did not fully solve runtime performance. For a trading platform, the browser must remain responsive while processing a continuous stream of market prices, order updates and position changes.

Traditional Angular applications commonly use zone.js to monitor asynchronous browser activity. Events such as clicks, timers, API responses and WebSocket callbacks can prompt Angular to check whether the interface needs to be updated.

That programming model is convenient, but it becomes expensive when events arrive at market frequency. A single price update should not cause unrelated components to be inspected, and a frequently changing value should not create a chain of new objects that increases memory usage and garbage collection.

We therefore moved Dhan Web to a zoneless architecture and used Angular Signals to make state updates more precise. The migration combined OnPush change detection, targeted Signal-based state updates, WebSocket handling in a Web Worker, browser-frame-aligned visual updates and more efficient event and lookup paths. We also audited callbacks, overlays, dialogs and isolated component trees to ensure the interface continued to update correctly under explicit change detection.

We also moved WebSocket message handling to a Web Worker so that receiving and processing every raw market tick would not occupy the browser’s main UI thread.

When the socket ran on the main thread, an incoming onmessage callback could trigger change detection. Updating application state with the processed market data could then trigger change detection again. In effect, the same tick could contribute to two change-detection triggers: one when the message arrived and another when the state changed.

By moving socket processing to the worker, we removed the onmessage callback as a main-thread change-detection trigger. The worker processes the incoming feed outside the UI thread and sends only the data required by the application back to the main thread, where Signals update the relevant consumers. This removed one of the two common triggers on the market-feed path, effectively halving the change-detection entry points associated with each processed update.

Angular can coalesce multiple change-detection requests into batches instead of executing every request independently. Even with this behaviour, taking WebSocket processing off the main thread reduced these batches by a meaningful margin, lowering main-thread pressure and leaving more capacity for rendering and user interactions.

Signals were applied according to the frequency and purpose of the state rather than being used mechanically everywhere. High-frequency market-feed values were treated differently from lower-frequency application state. When a signal changes, Angular can identify the consumers that depend on it instead of broadly checking unrelated parts of the interface.

For live market data, this gave us a more direct path from an incoming update to the affected screen element. Combined with targeted OnPush rendering and requestAnimationFrame, it reduced unnecessary main-thread work and helped lower browser CPU utilisation during continuous updates.

We also changed the way frequently updated LTP values were handled. Instead of creating a new object for every tick, appropriate values could be updated in place. Fewer short-lived objects meant lower memory churn and less garbage-collection pressure during active market sessions.

Removing zone.js itself saved approximately 35 KB, but the larger benefit was architectural: Dhan Web moved from broad automatic checks to explicit, dependency-aware updates.

This represented a fundamental shift—from asking Angular to repeatedly inspect the application to telling it exactly what changed and which consumers needed to respond.

Optimising the Market-Tick Path

The market-tick path required special attention. A browser-based trading platform has two distinct responsibilities:

  1. Receive relevant market updates without introducing unnecessary delay.

  2. Convert those updates into visual changes without overwhelming the browser.

Dhan’s market-data infrastructure continues to disseminate updates as they are received. On the frontend, however, we optimised the work performed after an update reaches the browser.

Previously, some frequently changing values could cause new objects to be allocated for each update. At the scale of live market data, these small allocations can accumulate quickly and increase garbage-collection activity.

For appropriate high-frequency values, we moved to in-place updates. We also introduced more targeted component refreshes so that an update to one security did not require unrelated sections of the interface to be checked.

Where suitable, rendering was aligned with the browser’s animation frame. This allowed us to maintain the freshness of the underlying data while fitting applicable visual work more naturally into the browser’s rendering cycle.

Every tick may change the market, but every tick does not need to re-render the entire application.

This distinction is critical. Data delivery and screen painting are related, but they are not the same operation. The latest state can be maintained continuously while the browser performs visual updates efficiently.

Preserving Expensive Screens during Navigation

Trading applications contain screens that are expensive to initialise. Advanced visualisations, large data grids and information-dense trading views may require significant setup work.

Destroying and recreating these screens whenever a trader navigates between sections introduces avoidable delays. It may also require restoring state, reinitialising subscriptions and rebuilding visual elements.

We changed the navigation architecture so that expensive trading screens could remain persistent when appropriate. Instead of reconstructing the complete screen after every navigation event, its state and rendering environment could be retained within the application shell.

We also reduced global styling overhead. Feature-specific styles that were not required on the initial screen were moved closer to their respective routes. Customers opening the platform no longer needed to download and process styling for features they had not yet visited.

Fixing Font Loading and Visual Stability

Some performance issues are caused by sophisticated architectural decisions. Others result from small configuration details that silently affect every customer.

Our fonts were marked for preloading, but the preload configuration was incomplete. Without the correct font resource attributes and cross-origin configuration, the browser could not reuse the preloaded resource as intended.

After correcting the configuration, fonts began preloading properly. This contributed to a significant improvement in Cumulative Layout Shift, or CLS. CLS measures unexpected movement of content while a page is loading. Such movement can be especially distracting in a dense trading interface where controls, values and actions must remain visually stable.

CLS reduced from 0.176 to 0.001 - an improvement of approximately 99%. We also deferred non-critical analytics scripts and removed other blocking work from the initial page.

These changes may seem small individually, but frontend performance is often the compound result of many carefully executed improvements.

Auditing More than the Happy Path

Moving to explicit change detection required us to examine the application beyond its primary screens.

Dialogs, overlays, callbacks and dynamically created components can behave differently from components inside the main application tree. If they are missed during a zoneless migration, the underlying data may change without the interface reflecting the update.

We reviewed 20 dialog and overlay flows and audited callback-heavy logic across 108 files. We also verified complete routes and user journeys from end to end.

The optimisation covered more than 300 frontend units and uncovered several functional issues along the way. These were corrected as part of the migration.

A major performance refactor should not be treated as a purely mechanical exercise. It is also an opportunity to validate assumptions, document flows and simplify years of accumulated application behaviour.

Measuring the Results from the updates

We measured the impact across bundle weight, startup execution, Total Blocking Time, Cumulative Layout Shift, Speed Index, build-budget compliance and overall Lighthouse performance. The results showed a lighter startup path, less main-thread blocking, stronger visual stability and more headroom within the build budget.

Beyond synthetic scores, the browser now performs less work during startup, uses Signals to update only the consumers affected by live market data, creates fewer short-lived objects and reduces unnecessary CPU, memory and garbage-collection work during active trading sessions.

What We Learned in the Process

A smaller bundle is only the beginning

Downloading less JavaScript is important, especially on slower networks and lower-powered devices. But runtime behaviour matters equally. A smaller application that triggers excessive work for every market event can still feel slow. Load performance and runtime responsiveness must be optimised together.

High-frequency state needs a different model

Signals were most valuable when applied according to the frequency and purpose of the state. High-frequency market data needs targeted, dependency-aware updates; otherwise, broad change detection and repeated object allocation can consume CPU and memory even when most of the interface has not changed.

Lazy loading must follow customer behaviour

The correct boundary for lazy loading is not necessarily a technical module boundary. It should reflect how customers use the product. If a capability is not required for the first meaningful interaction, it should be evaluated for on-demand loading.

Long trading sessions require a different testing approach

A trading platform may remain open for several hours. Performance must therefore be tested not only immediately after startup but also after prolonged usage, repeated navigation and sustained live-data processing. Memory allocations, subscriptions and component lifecycles become increasingly important over time.

Performance budgets must be enforced continuously

A one-time optimization can be reversed gradually as new capabilities are added. Bundle budgets, route-level analysis and performance checks must become part of the development lifecycle. Performance should be reviewed with the same seriousness as reliability and functional correctness.

What comes next from us on Web Platforms

This optimisation has created a much stronger foundation, but performance engineering is never finished. Our next focus is to break long startup tasks into smaller units, stagger non-critical API requests, further reduce main-thread blocking and lazy-load more secondary resources and routes. We will also continue reducing unused JavaScript and global CSS while tightening performance budgets for future releases.

We are expanding real-user monitoring across devices and network conditions and measuring responsiveness during real market volatility. Synthetic benchmarks help us understand progress, but the most important measurement remains the experience of a trader using Dhan under real market conditions.

The browser is part of the Trading System

At Dhan, we think about performance as an end-to-end journey.

A market tick moves from the exchange through our market-data infrastructure and reaches the customer’s device. It then has to be processed, associated with the correct security and rendered in the appropriate part of the interface.

When markets are moving quickly, every part of the journey - from market tick to browser - must be built for speed.

Similarly, an order begins with a customer interaction in the browser before it reaches DEXT and ultimately the exchange. The browser is therefore not merely a presentation layer. It is the final component of the trading experience.

Optimising Dhan Web meant making that component download less, execute less, update more precisely and retain expensive application state wherever appropriate.

Concluding Notes - as we always have said and done, your experience on Dhan gets better everyday!

For us, performance is not a one-time project or a score displayed by a testing tool. It is a continuous engineering discipline.

Kind Regards
Alok

14 Likes

Welcome, 10x UI gains! :rocket:

DEXT was already super fast, but the app and web experience often lagged behind like a sports car held back by a heavy trailer blocking its path.

Hopefully, this brings the much-needed speed gains to the frontend and finally lets the UI reflect DEXT’s speed better.

Thanks, @Alok_Pandey and Dhan! :raising_hands:

2 Likes

True. This is much needed. Sahi’s snappy performance is something Dhan could learn from.