# Server-side logic and logs

> Where your app's logic runs, which parts are enforced away from the browser, and how to read your app's runtime logs.

"Where does my code actually run?" matters the moment something works in a way you did not expect. This page explains where a Vaulter app's logic lives, which parts run away from the user's browser, and how to read your app's logs when behavior surprises you.

## Where your app's logic runs

A Vaulter app has two halves:

- **The interface** runs in each visitor's browser: pages, forms, interactivity. This is the code you see in the [code editor](/docs/your-app/code-editor).
- **The backend** runs on Vaulter's managed infrastructure: the [database](/docs/data/database) with its [privacy rules](/docs/data/data-privacy), [sign-in](/docs/auth/add-sign-in), file storage, and every [connector call](/docs/integrations/connectors), which travels through Vaulter's secure routing so credentials never reach the browser.

The important consequence: the security-relevant logic does not depend on the browser behaving. Privacy rules are enforced by the database itself and connector limits by Vaulter's servers, so a clever visitor with the developer console open cannot switch them off.

## What "server-side" the agent can build

Most requests that sound server-side land in that managed backend without you thinking about it: "only the owner can see this" becomes a database rule, "charge the customer" becomes a routed Stripe call, "email a confirmation" a routed Resend call. Describe the behavior and the agent places the logic on the right side.

The honest boundary: Vaulter does not currently run arbitrary always-on server code you write, such as a custom background worker or a cron job that runs while nobody has the app open. If a feature genuinely needs that shape, [Known limitations](/docs/reference/limitations) covers the workarounds; often a small redesign ("run the check when the owner opens the dashboard") gets the outcome without it.

## Reading your app's logs

Open **Vault → Database → Logs** for the app's real runtime output while you build: console messages, network requests, and uncaught errors from your own app code running in the preview.

- Filter by level (info, warnings, errors) and by window (last 15 minutes, hour, or day).
- The habit that pays: reproduce the problem in the preview, then open Logs and read the newest entries. An error with a message beats "it does not work" as a prompt; paste it into chat.
- These are the preview's logs. For a problem that only shows on the published app, reproduce it in the preview first; the code is the same, so the error almost always shows there too.

## Frequently asked

#### Do I need to know which side a feature runs on?

No; the agent decides, and this page exists so its choices are not mysterious. The one habit worth keeping is to state security intent explicitly ("only admins can approve refunds"), because that phrasing tells the agent the rule must be enforced by the backend, not just hidden in the interface.

#### Can my app receive webhooks from other services?

Receiving inbound events from an outside service (a payment settled, a form submitted elsewhere) is not a supported feature today. Tell [support](/docs/reference/troubleshooting) what you are trying to build; often polling the service through its connector on page load achieves the same outcome.

#### The logs are empty

Logs show activity, so make some: open the preview and use the feature in question, then refresh the Logs view. If the widest time window is still empty after that, the app is not logging anything, which for a healthy app is normal.
