DEV Community

Cover image for The Web Was Never Designed for Business Applications
Theodoros Bebekis
Theodoros Bebekis

Posted on

The Web Was Never Designed for Business Applications

The Web won the battle for the distribution of business software. An application can be installed on a server, updated in one place, and made immediately available to people working from different offices, cities, or countries. The browser is almost everywhere, and accessing an application does not require a separate installation on every computer.

This success often conceals a fundamental contradiction. The Web became the dominant platform for delivering business applications, even though it was not designed for the way they work.

The Web was designed around documents, pages, links, and independent requests. Business applications are environments for continuous work on data. They require long-lived state, active tasks, datasets, rules, commands, permissions, and controlled transitions between business states.

Today's browser can host extraordinarily complex applications. To achieve this, however, we have to build inside it much of an application runtime that the Web did not provide by nature.

Two Application Models, One Browser

The term web application is used for two fundamentally different kinds of software. To discuss their differences clearly, we need to give them names.

The first is the document-oriented model. Such an application is organized around documents or pages, content, rendering, and navigation. The user visits a page, consumes content, follows links, and usually performs small, relatively independent interactions.

A news site, a blog, a public corporate website, and much of an online store follow this model. They may include dynamic content, search, user accounts, and forms. Their fundamental unit remains the page, or the content presented within it.

The second is the desktop-like application model. The term describes neither the application's appearance nor the operating system on which it runs. It describes its model of interaction and work.

In a desktop-like application, the user works continuously. They open tasks and keep them active, edit data over extended periods, move among lists, forms, and business objects, execute commands, deal with validation errors, and manage changes that have not yet been saved. The application participates in processes with state, rules, permissions, and history.

The back office of an online store is a characteristic example. A visitor browsing products primarily uses a document-oriented application. An employee managing orders, inventory, returns, and payments uses a desktop-like application, even when both run in the same browser.

The distinction can be summarized simply.

A document-oriented application is primarily visited and navigated.

A desktop-like application is primarily operated and worked in.

The two types can coexist within the same system and share data and services. They remain, however, different application models. When they are treated as variations of the same problem, architectural discussions become vague and tools are judged by the wrong criteria.

A Platform Built Around Documents

The Web's original architecture was designed to distribute and connect documents.

HTML describes documents. The DOM represents a document tree. URLs identify resources. HTTP is organized around independent requests and responses. Navigation moves the user from one page to another. The classic web form collects a limited set of values and submits them to the server.

This model is highly effective for content. A document can be requested, transferred, presented, and replaced by the next one. The state that must remain on the client is limited.

A desktop-like business application demands different things.

  • Multiple active work areas.
  • Data that remains loaded and related.
  • Editing sessions containing both saved and unsaved changes.
  • Master-detail coordination.
  • Dirty tracking across fields, records, and object graphs.
  • Validation at different levels.
  • Commands whose availability depends on state and permissions.
  • Complex grids, lookups, and search tools.
  • Controlled lifecycles and business transitions.
  • Protection against concurrent work and conflicting changes.

A user may be editing an order, open a customer's record to check some information, return to the order, and continue from where they left off. The application must know which data is loaded, what has changed, which commands are allowed, and what should happen if the user closes an active task.

This is not navigation among documents. It is the management of state and work.

Rebuilding an Application Platform Inside the Browser

Modern browsers are powerful execution environments. JavaScript, Web APIs, and today's frameworks make it possible to build applications that only a few years ago would have been considered exclusively desktop software.

This capability, however, does not erase the platform's architectural origins. To host a desktop-like application, the browser must effectively acquire an application runtime.

JavaScript frameworks provide components, rendering, reactivity, routing, and general state-management mechanisms. These are important building materials. On their own, they do not constitute a model of business work.

Developers often need to select, combine, or build additional mechanisms for:

  • datasets and field metadata,
  • editing state and change tracking,
  • master-detail coordination,
  • data-aware controls,
  • commands and command availability,
  • validation and error presentation,
  • lookup and reference resolution,
  • control lifecycles,
  • saving complex object graphs,
  • concurrency and transaction boundaries.

Some of the complexity of a modern web application belongs to the business problem itself. Rules, permissions, processes, and data relationships would exist on any platform.

Another part is the cost of adaptation. It is the work required to turn a document-oriented environment into an application platform.

This distinction matters in practice. If we attribute all complexity to the business domain, we will never recognize which problems recur in every business application because the appropriate runtime is missing. We will continue solving them again in every project, using different combinations of libraries and local conventions.

The Distinction the Web Literature Failed to Make

Despite its practical importance, the distinction between the document-oriented and desktop-like application models has rarely been stated explicitly in Web literature and commentary. Discussions have been organized primarily around technologies and implementation mechanisms, such as server-side rendering, Single Page Applications, components, native clients, and cross-platform frameworks. Classifying the kind of application and the work it must support did not come first.

This was a taxonomic and architectural mistake. Every application that used HTTP and appeared in a browser was called a web application, as though sharing a platform implied sharing the same needs. As a result, techniques suited to distributing documents and content were applied to systems for continuous data processing, while rich-client architectures were proposed even for applications whose natural unit remained the page.

The public-facing side of an online store requires a fast initial display, search-engine discoverability, and effective content presentation. The back office of the same store requires stable editing sessions, dense data presentation, fast keyboard navigation, complex grids, validation, and safe business actions. A shared platform does not imply a shared application model.

The same confusion found its way into JavaScript libraries and frameworks. The ecosystem offered general mechanisms for components, rendering, routing, and state, but more rarely a coherent model for datasets, editing sessions, data-aware controls, commands, master-detail work, and controlled lifecycles. These capabilities can be built, but the creator of a business application is often left to assemble the corresponding runtime alone.

The late arrival of techniques such as virtual scrolling in grids is a simple example. Working efficiently with tens or hundreds of thousands of records is a common requirement in business software, but it was not an early priority for an ecosystem oriented mainly toward pages and content.

Many of these tools solve the problems for which they were designed effectively. Their generality, however, does not automatically make them suitable for every kind of application. The architectural decision must begin with the model of work and only then consider the implementation mechanism.

The correct order of questions is simple. First, we decide whether the application functions primarily as a document or as a program for continuous work. Then we decide whether it needs SSR, an SPA, hydration, a native client, or some combination of them. The literature and the ecosystem have all too often followed the opposite order.

The Long Road Back to the Server

The evolution of the JavaScript ecosystem illustrates the consequences of this confusion. Early web applications relied mainly on server-side rendering. The server produced the HTML, and the browser presented the result. This model was a natural fit for document-oriented applications, but it limited the immediacy and continuity of work required by many desktop-like applications.

Single Page Applications moved much of the rendering and interaction to the client. The initial page loaded a JavaScript runtime, which requested data and changed the interface dynamically. This approach enabled fast transitions, rich interaction, and state preservation without a full page reload.

The SPA was a reasonable response to the needs of desktop-like applications. The mistake was generalizing it into an almost self-evident architecture for every web application.

When much of the application moved into the browser, the client took responsibility for navigation, temporary state, caching, synchronization, communication error handling, and a substantial part of the application flow. Routers, state managers, package managers, bundlers, build pipelines, code splitting, and client-side caches became necessary to control the complexity. Each new addition solved real problems. Many of those problems, however, had been created or amplified by the previous transfer of ever more responsibilities to the client.

The browser thus began to operate as a second application server. At the same time, the application still had to keep authorization, definitive validation, and control of shared state on the actual server. The same logic often appeared on both sides, with different implementations and different lifecycles.

Newer approaches, such as hydration, partial hydration, islands, and server components, move parts of rendering and execution back toward the server. They address real problems involving initial load, performance, discoverability, and JavaScript volume. At the same time, they reveal that moving the entire application to the client was not the natural choice for every case.

After years of increasing client complexity, the ecosystem is rediscovering that server-side rendering is not an obsolete technique for many document-oriented applications. It is often the simpler and better architectural choice. Content arrives ready to display, navigation remains straightforward, and the client handles only the interaction that is genuinely needed.

For desktop-like applications, a rich client often remains necessary. A long-lived editing session, a complex grid, and immediate responses to continuous user actions require substantial execution on the client. An SPA, however, provides the container, not the business model. Components and reactive state are not equivalent to datasets, a command system, transaction boundaries, and a controlled lifecycle.

The return to the server does not prove that SPAs were entirely wrong. It proves that architecture must follow the kind of application. Document-oriented applications can use SSR and add client-side behavior where needed. Desktop-like applications can use a rich client, but they require a genuine application runtime and a centrally controlled business model.

The essential question is not whether the browser can execute more logic. It can. The question is which logic genuinely needs to be there.

JSON Is Not the Problem

Data transfer reveals the same confusion on a smaller scale.

JSON is simple, readable, and supported almost everywhere. It is an excellent fit for configuration, small object graphs, and many kinds of API responses. The problem begins when every set of business data is mechanically represented as an array of independent objects.

An equipment catalog can be transferred as follows.

[
  {
    "id": "3ec5070e-cedd-49e9-95de-c3b249c5231a",
    "code": "EQ-104",
    "name": "Portable Projector",
    "category": "Presentation",
    "available": true
  },
  {
    "id": "593c227a-c1bc-423a-8a53-03f984e86e65",
    "code": "EQ-127",
    "name": "Conference Speakerphone",
    "category": "Audio",
    "available": true
  },
  {
    "id": "787085b0-b3cf-4b53-919a-d6cffaf98e8c",
    "code": "EQ-143",
    "name": "Document Camera",
    "category": "Presentation",
    "available": false
  }
]
Enter fullscreen mode Exit fullscreen mode

The format is clean and convenient. For a small number of records, repeating property names has no practical significance.

In a large dataset, however, the same names are repeated in every row. Schema information remains implicit. The client must obtain types, captions, nullability, lengths, editability, and presentation rules from elsewhere. The representation also has no natural place for row state, original values, deleted rows, and change tracking.

JSON remains merely the format. The substantive decision is the model we choose to express within it.

A Dataset Is More Than an Array of Objects

A dataset is an organized collection of rows that share the same schema. Fields have names, types, and metadata. Rows can have state and participate in an editing session. This nature can be represented explicitly.

{
  "name": "Equipment",
  "fields": [
    {
      "name": "id",
      "dataType": "string",
      "required": true,
      "readOnly": true,
      "visible": false
    },
    {
      "name": "code",
      "dataType": "string",
      "caption": "Code",
      "required": true,
      "maxLength": 20
    },
    {
      "name": "name",
      "dataType": "string",
      "caption": "Equipment",
      "required": true,
      "maxLength": 120
    },
    {
      "name": "category",
      "dataType": "string",
      "caption": "Category",
      "required": true,
      "maxLength": 60
    },
    {
      "name": "available",
      "dataType": "boolean",
      "caption": "Available",
      "required": true,
      "defaultValue": true
    }
  ],
  "rows": [
    {
      "state": "unchanged",
      "values": [
        "3ec5070e-cedd-49e9-95de-c3b249c5231a",
        "EQ-104",
        "Portable Projector",
        "Presentation",
        true
      ]
    },
    {
      "state": "modified",
      "values": [
        "593c227a-c1bc-423a-8a53-03f984e86e65",
        "EQ-127",
        "Conference Speakerphone",
        "Audio",
        false
      ],
      "originalValues": {
        "available": true
      }
    },
    {
      "state": "inserted",
      "values": [
        "a64dc71c-3b37-4442-b28b-2140307e711d",
        "EQ-151",
        "Wireless Presentation Kit",
        "Presentation",
        true
      ]
    }
  ],
  "deletedRows": [
    {
      "id": "787085b0-b3cf-4b53-919a-d6cffaf98e8c",
      "version": 4
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

The schema is transferred once. The values in each row follow the order of the fields, without repeating their names. Metadata can guide editors, validation, and presentation. The state of each row is expressed explicitly, while changes and deletions can be retained until the data is saved.

This representation is not proposed as a universal replacement for conventional JSON. For a small response or an independent object, it would often be unnecessarily complex. In an application that loads, presents, and edits large sets of homogeneous records, it expresses the nature of the data more accurately.

The benefit is not limited to reducing the payload. A dataset-aware runtime knows which fields exist, what they are called, which value types are expected, and which rows have changed. It can connect this data to grids, editors, validation, and commands without every screen inventing its own model.

Data representation is part of the architecture. When a business dataset is treated as an arbitrary collection of objects, its structure and behavior must be reconstructed elsewhere.

Business Software Deserves Its Own Model

Business software is one of the largest categories of software being built. Businesses and organizations need applications for sales, purchasing, inventory, finance, personnel, manufacturing, projects, services, approvals, and countless specialized tasks.

Despite its scale, business software is often described using general concepts such as pages, components, state, and API calls. These concepts are useful, but they operate at a lower level than the actual problem.

A business application is organized around business objects, datasets, references, rules, actions, lifecycles, roles, and persistent state. Users do not operate components. They submit requests, approve actions, reserve resources, correct information, and complete tasks.

Recognizing the desktop-like application model is neither a return to the desktop nor an attempt to imitate old user interfaces. It means recognizing continuous, stateful, data-intensive work as a distinct application model, regardless of the platform on which it runs.

A desktop-like application may be a native desktop, web, or tablet application. Conversely, a desktop application may be primarily document-oriented. The terms describe the nature of the interaction, not the delivery medium.

This distinction enables more precise decisions. A framework suited to content is not automatically suited to dense business work. A component library is not equivalent to a business application runtime. An API that serves independent resources well does not necessarily support object graphs, commands, and editing sessions.

Business software needs its own vocabulary and tools that recognize its recurring structures. Without them, every team builds fragments of the same foundation beneath its application screens.

Use the Web for What It Does Best

The Web remains an excellent delivery medium. Universal access, centralized deployment, immediate updates, and natural support for distributed users rightly explain its dominance.

The architectural conclusion is not that we should abandon the Web. It is that we should use it with an understanding of its nature.

The business model needs an existence independent of the browser and the UI framework. Data, relationships, rules, commands, and lifecycles must be defined in business terms. The UI is the projection of and interaction mechanism for that model, not the place from which the model emerges.

With this foundation, the same business model can support different presentation environments. The Web can provide broad distribution. A desktop client can take advantage of deeper integration with the operating system. A mobile client can serve selected tasks suited to the device and its context of use.

The choice of platform thus ceases to determine the nature of the application. The application retains its business model, and each client presents it in a way appropriate to its own environment.

The Web won because it can deliver business software everywhere. That does not mean it naturally understands business software.

The Web won because it can deliver business software everywhere. That does not mean it naturally understands business software.

Top comments (0)