DDRW editorial team ·

How a modern web service works: from click to response in 10 diagrams

We explain a web service using an online store: browser, server, database, Redis, sessions, payments and background jobs. Ten diagrams trace the journey from a click to a confirmed order.

In this articleSections: 10
3D web service illustration: a browser window, server modules and data storage connected by transparent channels

A buyer opens a product, chooses a size, signs in and pays for an order. On screen, these are a few understandable actions. Inside the service, the browser, application server, database, cache, payment system and background workers each contribute their part of the result.

Good architecture describes more than the successful path. It explains what happens if an item sells out, the bank’s response is delayed or an email is not sent. Otherwise, a convenient interface conceals uncertainty that someone must later resolve manually.

We examine a hypothetical store through ten diagrams, from the first product-page request to payment, email and recovery after failure. This is a teaching example rather than a description of verified properties of a specific DDRW project. Not every store needs a separate server for each component: a small application can combine them in one process while keeping clear responsibility boundaries.

1. The request path: what happens after a click

Diagram 1: the request travels from the browser through the application server to data and back to the user

When a page opens, the browser requests its address and receives an HTTP response: status, headers and content. This could be a product page’s HTML, an image or data for an interface update. The basic “client requests, server responds” cycle is explained in MDN’s introduction to how the web works.

One visible page usually needs several resources. HTML defines its structure, CSS its styling, images show the product, and client code handles color selection. The browser may obtain some resources from its own cache, so reopening a page does not necessarily repeat the entire network journey.

A reverse proxy often sits in front of the application. It accepts connections, directs requests to the appropriate handler and may serve static files separately. The application determines whether a product exists, whether it is published and what data may be shown.

In our store, a successful product-page response does not yet mean the purchase can be completed. Price and stock can change between browsing and checkout. These are different operations with different checks.

For diagnosis, distinguish connection establishment, waiting for a response, resource loading and rendering. If a photograph is too large, speeding up an SQL query will not solve the whole problem. If the server waits too long for an external service, replacing an animation will not remove the delay either.

2. DNS and HTTPS: locating an address and protecting transmission

Diagram 2: resolving a domain name through DNS and establishing a secure HTTPS connection

DNS helps map a domain name to a network address. The result may already be cached in the browser, operating system or DNS resolver. A request therefore does not always begin with a complete fresh name lookup.

DNS does not deliver the product page, read the catalog or verify payment. Changing DNS sends future requests to different infrastructure but does not itself move the application or its data. A migration needs to consider record caching and availability at both the old and new locations.

HTTPS uses TLS to protect transmission between the connection’s parties. The browser checks the certificate and domain, and the parties negotiate a protected exchange. TLS purposes and properties are described in MDN’s documentation.

This protection matters for login, carts and checkout, but it guarantees neither an honest store nor correct business logic. A website with a valid certificate can still calculate a total incorrectly or allow access to someone else’s orders.

If TLS terminates at a proxy, consider the connection from that proxy to the application separately: where it runs, who can access it and whether additional protection is needed. Passwords, tokens and buyer data cannot be considered protected across every internal component merely because the address bar shows HTTPS.

3. Frontend and backend: where decisions are made

Diagram 3: separating responsibilities between the browser interface, server logic and data storage

The frontend helps people interact with the store. It shows available colors, changes photographs, checks obvious form errors and explains action results. The backend applies business rules and determines which changes are permitted.

For example, the browser can instantly show a provisional total when “plus” is clicked. At checkout, however, the server rechecks the product variant, quantity, current price and order conditions. A total supplied by the client cannot be trusted: a request can be sent without using the store interface.

The same applies to management controls. Hiding a refund button improves the buyer’s interface but does not prevent calls to its endpoint. The server checks authorization for a financial action independently of how the request was formed.

The frontend/backend boundary does not have to lie between two separate applications. A server can generate pages and accept ordinary forms while interactive elements call an API. What matters is an authoritative server implementation of calculation rules and operation permissions.

For checkout, distinguish errors by meaning. An incorrect phone number needs correcting in the form; a sold-out size needs reselecting; a temporary payment failure needs waiting or an agreed alternative. A universal “Something went wrong” message does not help the purchase continue and complicates support.

4. SSR, hydration and interactivity: what the browser receives

Diagram 4: server-prepared HTML, hydration of interactive elements and subsequent navigation within the application

With SSR, the server prepares page HTML before sending it to the browser. The product page can already contain a name, description, price and main image. Users do not necessarily have to wait for another API request just for this text to appear.

Hydration connects client logic to the server-rendered view. It is needed where the interface should respond without a full document reload: switching a variant photo, opening a gallery or recalculating a provisional total. The approaches are compared in web.dev’s article on rendering.

SSR does not mean no JavaScript. An application can send finished HTML and a large client bundle at the same time. Code volume, loading order and interactivity boundaries remain separate decisions.

Islands architecture is one way to limit interactivity to particular parts of a page. A product description can remain static while size selection and the cart receive their own client logic. This is not an automatic property of every SSR application.

In an SPA, internal navigation can update the view without reloading the whole document. The server still validates data and action requests. Opening an address directly also needs a correct response: a search result does not have to begin at the homepage.

Initial server and client data must agree. If the server shows one product variant while the first client render selects another, jumps and errors can occur. Prefilling a personal cart needs a separate caching policy: a personalized response must not be served to the next visitor from a shared cache. Sensitive pages commonly use no-store.

5. Databases and transactions: saving a consistent order

Diagram 5: checking the product and stock, creating an order snapshot and committing changes in a database transaction

The database stores products, variants, stock, customers and orders. Their relationships are useful for management, but a placed order must not depend on a future product rename or catalog price change.

An order therefore keeps a snapshot of important conditions: name, variant, quantity, price and total. These are separate purchase-time data. A link to the current product may remain, but cannot replace the snapshot.

A transaction groups database changes on an “all or nothing” basis. If saving one required part fails, the other changes in that operation should not remain partly applied. See PostgreSQL’s explanation of transactions.

For the last available size, reading stock and reducing it in a later independent operation is insufficient. Two buyers can read the same value. Choose a concurrency-control mechanism: a lock, conditional update or another agreed approach. Design conflict behavior explicitly.

In our example, the server checks conditions, creates the order and reserves the product under store rules within a short transaction. A reservation has an expiry and a clear release procedure if the buyer does not pay.

External payment is not part of this SQL transaction. A bank will not reverse a charge because the store database rolls back. Use separate states, saved identifiers and subsequent reconciliation. Nor should a transaction remain open while someone fills in the bank’s form.

6. Redis and caching: faster reads without bypassing rules

Diagram 6: reading the catalog through Redis, falling back to the database on a miss and refreshing the cache after data changes

In the hypothetical store, Redis holds a reconstructible copy of public catalog data. The application first looks for a ready value in the cache; on a miss, it reads the database and prepares a new copy. This is called cache-aside. See the Redis documentation.

A key must account for everything that changes the result: product, filters, language and data-format version. A shared cache must not hold other people’s carts, private orders or personal terms without suitable separation.

When a product changes, wait for a successful database commit. Clearing the cache earlier can let a concurrent request refill it with the old value. But a simple delete command after commit does not eliminate every race or notification-delivery failure either.

Stricter control uses data versions and reliable recording of update events. A TTL limits a copy’s lifetime but does not promise immediate freshness. Define acceptable delay and error behavior in advance.

At checkout, the server reads authoritative prices and stock through the agreed validation path instead of authorizing payment from a cached product page. User permissions cannot be considered current merely because they were once stored in a public cache.

If Redis is unavailable, catalog reads can fall back to the database, increasing load. Concurrency limits and monitoring are needed so a short cache outage does not overload the primary store.

7. Sessions, cookies and permissions: identifying users and checking actions

Diagram 7: login, session creation, sending a protected cookie, checking permissions and protecting state-changing requests against CSRF

Authentication asks “Who is making the request?” Authorization asks “What are they allowed to do?” Signing in does not give a buyer access to every order: the server verifies ownership of the particular order on each relevant request.

A session connects browser requests to a verified login. A cookie may contain a session identifier or a protected token, depending on the architecture. Either approach needs expiry, logout and a way to revoke access in the intended situations.

HttpOnly limits JavaScript access to a cookie, Secure is intended for transmission over a protected connection, and SameSite helps restrict sending cookies in cross-site scenarios. These properties do not replace permission checks or other application security measures.

Browsers attach matching cookies automatically. An attacker may therefore try to initiate a state-changing action through another website. Cookie authentication needs appropriate CSRF protection, including token and request-origin checks under the chosen scheme. SameSite limitations are covered in the OWASP guidance.

In our store, quantity changes, order creation and contact updates undergo server checks. Administrative actions need their own permissions. Fields such as user_id or role supplied by the browser do not prove authorization.

Guest-cart access also needs an ownership model. No registration does not mean public access: the server associates the cart with a secret issued to the visitor and does not reveal data based on a guessable number alone.

8. Queues and background jobs: continuing after the response

Diagram 8: saving a background job, a worker receiving it, retry attempts and protection against repeat execution

After creating an order, the buyer does not necessarily need to wait for an email to be sent. A background worker can do this separately. First, however, the need to send it must be saved reliably.

One approach writes the order and a processing event in the same database transaction. A separate process then reads events and performs tasks. The gap between saving the order and queueing its email no longer depends on the application completing a second network call.

Task delivery needs to allow for repeats. Standard Amazon SQS queues, for example, explicitly allow the same message to be received more than once and recommend idempotent processing. See the at-least-once delivery documentation.

Idempotency means a repeat produces no unwanted additional result. Processing a paid order can use a unique event, a checked state and a database constraint. A queue alone does not ensure a business action occurs “exactly once.”

Email is more complicated: the mail server may accept a message while its acknowledgment is lost. An automatic resend can create a duplicate. An uncertain state, available delivery identifiers and a defined investigation procedure are needed.

Bound retries, space them out and distinguish temporary errors from permanent rejection. In an administrative interface, showing the job, attempt count and latest stopping reason is useful. “Accepted by the mail server” is not proof of reading—or even arrival in the buyer’s inbox.

9. APIs, payments and webhooks: trusting verified events

Diagram 9: creating a payment session, redirecting the buyer to the provider, verifying a webhook and updating order status

The server creates a payment for a saved order through the provider’s API and records the connection between its internal order and the external payment identifier. The amount comes from the verified snapshot; integration secrets remain on the server.

The buyer opens the returned payment URL. Afterwards, the browser may return to a success, error or pending page. This navigation helps the person continue but does not prove money was received: a tab can be closed, an address opened manually, and the provider notification delivered later.

A verified server notification or an authorized provider-status query confirms state. The handler matches the order, payment, amount, currency and permitted status. Signature or token verification depends on the integration; HTTPS and a familiar field name do not replace this check.

Webhooks can repeat and arrive out of order. The need to authenticate them and handle repeats is shown in Stripe’s official documentation. This illustrates general principles; the chosen bank’s specific contract must be checked separately.

In our store, a repeated confirmation must not reduce stock or create another email again. The notification is handled transactionally with its result saved. A successful response is sent to the provider after the event has been reliably accepted; heavy follow-up actions can run in the background.

Cancelling an order, cancelling a payment and refunding money are different operations. Connect them through clear states and separate permissions. A network error during a refund also does not prove the bank did nothing: first establish the actual result.

10. Deployment, observability and recovery

Diagram 10: releasing an application, checking readiness, observing requests and restoring the database and files from backup

Deployment moves a prepared version into the live environment. In addition to the application, it needs a compatible database schema, configuration and access to files and secrets. A process responding to a readiness check does not prove the catalog, checkout and payment notifications are available.

A release plan considers database changes and rollback. Returning to an old application is unsafe if a new migration has already made the data incompatible with it. Background jobs and bank notifications may also continue arriving during the switch.

Observability helps explain the actual cause of a failure. Metrics show error rates and delays, logs record individual events, and traces connect parts of request execution. These signals and their purposes are described in the OpenTelemetry introduction.

For a store, tracing the path from order creation to confirmation and email through connected identifiers is useful. Tokens, payment secrets and full personal data must not become routine log contents.

A backup includes necessary data, uploaded files and information required to run a compatible version. Set retention and acceptable loss of recent changes beforehand. PostgreSQL documents several approaches: dumps, filesystem copies and continuous archiving. See the backup documentation.

An archive’s existence does not prove recoverability. A separate verified scenario is needed: restore a copy in isolation, check data and files and open key pages. Disable real messages and financial actions there so testing does not repeat live operations.

Practical checklist

  • The server checks totals, stock and data ownership independently of the interface.
  • An order preserves purchase conditions, and its payment has its own identifier and state.
  • Shared caches do not contain other people’s carts, credentials or personal responses.
  • Background jobs and webhooks allow safe repeat processing.
  • Payment and sending errors have clear investigation and resolution paths.
  • Releases account for database compatibility, and recovery is tested separately from backup creation.

Frequently asked questions

Do we need microservices from the start? No. These responsibilities can be implemented in one application. Physical separation is justified by load, independent development and team capabilities.

Is Redis enough for speed and reliability? No. Caching accelerates selected reads but does not fix slow queries, access-control errors or incorrect payment handling. Establish the cause of the problem first.

What matters most to check before launch? The complete journey and its failures: a product changes, a request repeats, payment is delayed, email is not sent, or the application restarts. Behavior in these situations is what makes the system manageable.

Related services and projects

Let’s discuss your project

Tell us about your product and the outcome you need. We will define the scope, propose an approach and agree on timing and cost.

All articles