> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xano.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Securing Your App Before Launch

> Lock down accounts, environments, and endpoints before your first real user shows up.

<Info>
  **Quick Summary**

  Xano secures the platform — JWE-based auth, single-tenant infrastructure on dedicated plans, encrypted data at rest, SOC 2 / HIPAA / GDPR compliance. What Xano can't decide for you is which endpoints should be public, which fields you return, who on your team can touch production, or whether the test accounts you seeded last month are still sitting in your database.

  This guide is the audit to run before pointing real users at your backend. Not every recommendation will apply to every project, but most will — work through each section and skip the ones that genuinely don't fit.
</Info>

## Platform security vs. application security

Xano's platform-level protections are real and they aren't optional — your data lives on infrastructure that's been hardened, audited, and certified. But there's a clear line between **platform security** (what Xano handles) and **application security** (what you decide), and most launch-day incidents come from the second one.

Application security covers everything that depends on choices only you can make:

* Who on your team can change production
* Where you build new features and how they get promoted
* Which endpoints are reachable from the internet
* What data those endpoints return
* What's still left in your database from prototyping

The most common shape of a launch-day incident is an endpoint the developer forgot they created. We call these **ghost endpoints** — live, reachable, unauthenticated, and not part of any feature anyone thinks they shipped. They usually originate from auto-generated CRUD during table setup, get forgotten, and never get revisited before launch. The audit below is structured to catch them, along with the rest of the sharp edges that tend to ship by accident.

***

## 1. Tighten Account & Team Access

Before you audit a single endpoint, make sure the people who can change your production app are the people who should be able to.

### Turn on 2FA for every account with workspace access

Two-factor authentication is the single highest-value protection on a Xano account. Anyone with workspace access — you, your teammates, contractors — should have it enabled. See [Enabling 2FA](/your-xano-account/account-page#enabling-2fa-two-factor-authentication).

If your plan supports it, the **Require 2FA** toggle in your instance [Security Policy](/xano-features/instance-settings/security-policy) makes this non-optional for the whole team.

### Review team members and their roles

Open your team list and remove anyone who no longer needs access — old contractors, former teammates, the agency that helped you prototype six months ago.

For everyone who stays, make sure their role matches what they actually do. Xano's [Role-Based Access Control](/team-collaboration/role-based-access-control-rbac) on Enterprise plans includes a dedicated **Workspace Live Data Source** permission, which is the gate between "can edit business logic" and "can read or modify production records." If you have a developer who builds features but shouldn't be able to query live customer data, that's the toggle.

See [Managing Team Members](/team-collaboration/managing-team-members) for adding, removing, and adjusting access.

### Rotate or revoke leftover Metadata API tokens

Any Metadata API tokens you generated during prototyping are still active until you revoke them. Walk your token list and:

* Delete tokens you no longer use.
* For tokens you keep, confirm the [scopes](/xano-features/metadata-api/token-scopes-reference) are the minimum the integration actually needs. A token with all scopes in the hands of a third-party automation has a bigger blast radius than most teams realize.

### Check the rest of the Security Policy

The instance [Security Policy](/xano-features/instance-settings/security-policy) panel covers a few other settings worth a look before launch:

* **Inactivity timeout** — how long a logged-in session can sit idle.
* **Allowed SSO hosts** — restrict logins to specific email domains (e.g., only `@yourcompany.com`).
* **Authentication enforcement** — require team members to log in via specific providers.
* **IP allowlisting / denylisting** — restrict who can reach the Xano dashboard.

***

## 2. Build Somewhere That Isn't Production

Most production accidents aren't malicious — they're a teammate running a quick test against the wrong data source, or a half-finished feature getting promoted before it's ready. Xano gives you several layers to keep those accidents off of production.

### Develop on a non-live data source

Your workspace can hold multiple [data sources](/the-database/database-basics/data-sources) — separate sets of records that share the same schema. Use a `dev` or `test` data source for everything that isn't a release, and reserve the live data source for production traffic. Switching is per-request, so the same function stack can run safely against either.

### Develop on a non-live branch

Xano workspaces support [branches](/team-collaboration/branching-and-merging), which are full copies of your business logic. Build new features on a non-live branch and only merge to the live branch when the feature is ready. Take a backup before merging — the branching doc covers the workflow in detail.

### Use the sandbox to preview changes before they land

The [sandbox](/testing-debugging/sandbox) is an isolated, ephemeral copy of your workspace that you push changes into first. You can inspect a full diff, run the changes, and verify behavior before promoting anything to a real branch. On paid plans, `xano workspace push` defaults to the sandbox flow specifically for this reason.

The combined pattern — non-live branch + non-live data source + sandbox preview — is what lets you ship confidently without standing up separate staging environments to maintain.

### Move secrets into Environment Variables

Anything sensitive hardcoded in a function stack — API keys, signing secrets, third-party tokens — should be moved into [Environment Variables](/building/logic/working-with-data/environment-variables). They're managed in one place, kept out of your function-stack values, and easier to rotate when something leaks.

### Clear test accounts and seed data from production

Prototyping leaves residue. Before launch, walk your production data source and remove:

* Test users with predictable credentials (`test@test.com`, `admin@admin.com`, anything with a password like `password123`)
* Seeded admin accounts you created to verify the auth flow worked
* Fixture rows from API testing — orders, posts, comments that aren't tied to anything real
* Backdoor accounts a teammate added for "just-in-case" access

A predictable test account on a live endpoint is functionally an unauthenticated endpoint. If you want to keep test users around for QA, move them to a separate data source.

### Confirm the Direct Database Connector is locked down

If you've enabled the [Direct Database Connector](/xano-features/instance-settings/direct-database-connector) for an external tool, make sure the IP allowlist is set to only the addresses that need it. A direct connection bypasses the function-stack layer entirely, including auth checks and rate limits — useful when you need it, risky when it's open.

***

## 3. Audit Your Endpoints

This is the part that catches ghost endpoints.

### Inventory every endpoint

Before you can secure your endpoints, you need to see all of them — including the ones you forgot about.

<Steps>
  <Step title="Open every API group">
    Click **API** in the sidebar. Walk through every API group and each API. Anything in here is potentially live the moment your instance is reachable.
  </Step>

  <Step title="List endpoints you can't immediately explain">
    For each endpoint, ask: "Is this part of a feature my frontend or another consumer actually uses?" If the answer is no, or "I'm not sure," flag it. These are your ghost-endpoint candidates.

    Common sources:

    * Auto-generated CRUD endpoints (`GET /table`, `POST /table`, `DELETE /table/{id}`, etc.) created during table setup
    * Endpoints created during prototyping that returned every field for debugging
    * Test or scratch endpoints that were never deleted
  </Step>

  <Step title="Delete, restrict, or keep">
    For every flagged endpoint, take one of three actions:

    * **Delete it** if it's not used. An endpoint that doesn't exist can't be exploited.
    * **Disable External Access** if you want to keep the logic but prevent public traffic. The endpoint will only respond to internal calls.
    * **Require authentication** if it should be reachable but only by signed-in users.

    These controls live in each endpoint's **Settings** panel — see [APIs](/the-function-stack/building-with-visual-development/apis#api-settings).
  </Step>
</Steps>

### Verify authentication on every endpoint that touches user data

Xano endpoints have an **Authentication** toggle in their settings. When it's off, the endpoint will respond to any caller, signed in or not. The default for new endpoints is **off** — you have to turn it on.

For every endpoint that reads, writes, or deletes user-scoped data:

1. Open the endpoint's **Settings** panel and set authentication to required.
2. In the function stack, filter queries by the authenticated user's ID (`auth.id`), not by an ID passed in the request. Authentication only proves *someone* is signed in; it does not stop user A from passing user B's ID.

A `GET /user/{user_id}` endpoint that requires auth but doesn't filter by `auth.id` will hand any user's record to any signed-in caller. This is the most common shape of a data-harvesting attack — register a real account, get a token, iterate IDs. UUIDs make iteration much harder, but they aren't a substitute for filtering correctly.

The two endpoints below both require auth. Only one of them is safe.

<CodeGroup>
  ```xs Insecure theme={null}
  query "users/{user_id}" verb=GET {
    api_group = "Users"
    auth = "user"

    input {
      int user_id { table = "user" }
    }

    stack {
      // Trusts whatever user_id the caller passed.
      // Any signed-in user can read any other user's record.
      db.get "user" {
        field_name = "id"
        field_value = $input.user_id
      } as $user
    }

    response = $user
  }
  ```

  ```xs Safe theme={null}
  query "me" verb=GET {
    api_group = "Users"
    auth = "user"

    input {}

    stack {
      // Always scoped to the caller's own record.
      db.get "user" {
        field_name = "id"
        field_value = $auth.id
      } as $user
    }

    response = $user
  }
  ```
</CodeGroup>

The same principle applies to writes: when patching or deleting user-owned records, either filter by `$auth.id` directly, or load the record first and verify its `created_by` (or equivalent ownership field) matches `$auth.id` before continuing.

### Lock down auto-generated API documentation

Each API group, and your workspace as a whole, has a **Swagger** setting that controls who can read its auto-generated documentation. The default is **Public**, which makes the full list of endpoints, methods, and inputs discoverable by anyone with the URL.

For production, set Swagger to:

* **Private (requires token)** — readable with the auto-generated token, which you can rotate or revoke.
* **Disabled** — docs aren't generated at all.

A locked-down Swagger setting doesn't make your endpoints secure on its own, but once you've finished the audit above there's usually no reason to publish a directory of every endpoint you have. See [Swagger / OpenAPI Documentation](/the-function-stack/building-with-visual-development/apis/swagger-openapi-documentation).

### Restrict CORS to origins you actually use

The default CORS configuration on a new API group is wildcard — any origin, any method, any header. That's fine during development; it isn't fine for a live app.

In **API Group Settings > CORS**, switch to **Custom** and:

* List only the origins that should be calling these APIs (production frontend, staging frontend, anything legitimate).
* Restrict allowed methods to the verbs your frontend actually uses.
* Restrict allowed headers to what you actually send.

CORS is browser-enforced, not a server-side firewall — it won't stop a determined attacker, but it cuts off the casual case of another website embedding calls to your API in a user's session.

### Flag sensitive fields so they don't land in logs

Xano keeps a [Request History](/maintenance-monitoring-and-logging/request-history) of incoming requests. Anything sent in a request body — passwords, tokens, PII — can end up stored there unless you mark the field as sensitive.

For every field that holds credentials, secrets, or regulated personal data:

1. Open the field's settings in the database table.
2. Enable **Sensitive Data**.

See [Sensitive Data Flagging](/security/best-practices#sensitive-data-flagging) for the details and the limits of the flag (it covers database-link inputs, not arbitrary function-stack outputs).

### Rate-limit endpoints that get hit hard

Paid Xano plans don't apply a default rate limit, which means a single attacker can iterate IDs against your endpoints as fast as their network and your instance allow. For obvious harvest targets — login, signup, anything that takes an ID and returns a record — add explicit rate limiting via the [Rate Limit function](/the-function-stack/functions/data-caching-redis#rate-limit). Key the limit by IP, by authenticated user, or by both.

If your plan includes [Middleware](/the-function-stack/building-with-visual-development/middleware), apply rate limiting (and other cross-cutting checks like role enforcement or suspicious-pattern logging) as middleware so a single rule covers a whole API group instead of being copy-pasted into every function stack.

### Verify webhook signature checks

If you accept incoming webhooks from third parties (Stripe, GitHub, etc.), confirm each one verifies the request signature before doing anything with the payload. The [Webhooks](/building-backend-features/webhooks) doc covers the `hmac_sha256` / `hmac_sha384` / `hmac_sha512` security filters used to compare a computed signature against the one in the request header. Without that check, anyone who knows the URL can forge a webhook.

***

## 4. Get Ready to Watch What's Happening

Once you launch, the question stops being "did I configure this right?" and starts being "is something happening I didn't expect?"

### Take a manual backup before launch

Xano keeps a rolling backup automatically, but it's worth taking a manual one right before your first real traffic — that gives you a clean restore point if something goes sideways in the first 24 hours. See [Backup and Restore](/xano-features/instance-settings/backup-and-restore) for retention details and how to take backups on demand.

### Know where to look when something looks off

Two surfaces, two different jobs:

* [Request History](/maintenance-monitoring-and-logging/request-history) — what's hitting your APIs. Watch for traffic to endpoints you didn't know were being called, repeated `GET`s with iterating IDs (classic harvest pattern), 401/403 clusters on endpoints nothing should be probing, and unfamiliar user agents.
* [Audit Logs](/xano-features/workspace-settings/audit-logs) — what's changing inside your workspace. Who edited which function, who deleted which table, who flipped a setting. If a teammate's account ever gets compromised, this is where you'll see the damage.

Open both right after launch and again the next day. Most issues that catch teams off guard are visible in one of these two places hours before they become a real problem.

***

## Pre-Launch Security Checklist

Once you've worked through the sections above, confirm:

**Account & team**

* [ ] 2FA enabled on every account with workspace access
* [ ] Team list reviewed; old or unused accounts removed
* [ ] RBAC roles match what each person actually needs to do
* [ ] Metadata API tokens audited — unused ones revoked, scopes minimized
* [ ] Instance Security Policy reviewed (inactivity, SSO hosts, IP rules)

**Environments**

* [ ] Development happens on a non-live data source
* [ ] Development happens on a non-live branch
* [ ] Sandbox previews used before promoting changes
* [ ] Secrets moved into Environment Variables (no hardcoded keys)
* [ ] Test accounts and seed data cleared from production
* [ ] Direct Database Connector locked down or disabled

**Endpoints**

* [ ] Walked every API group and identified every endpoint
* [ ] Deleted endpoints that aren't used by any consumer
* [ ] Disabled **External Access** on internal-only endpoints
* [ ] Enabled **Authentication** on every endpoint that returns or modifies user-scoped data
* [ ] Verified function stacks filter by `auth.id` rather than trusting IDs from the request
* [ ] Set Swagger to **Private** or **Disabled** on production API groups
* [ ] Replaced wildcard **CORS** with an explicit list of allowed origins, methods, and headers
* [ ] Flagged every field carrying credentials, secrets, or regulated PII as **Sensitive Data**
* [ ] Added rate limiting to login, signup, and other obvious harvest targets
* [ ] Applied centralized [Middleware](/the-function-stack/building-with-visual-development/middleware) for cross-cutting auth and rate-limit rules where available
* [ ] Confirmed every incoming webhook verifies its signature

**Operational**

* [ ] Manual backup taken right before launch
* [ ] Reviewed [Request History](/maintenance-monitoring-and-logging/request-history) for traffic against endpoints you can't explain
* [ ] Reviewed [Audit Logs](/xano-features/workspace-settings/audit-logs) for unexpected workspace changes

***

## Related

* [Security Best Practices](/security/best-practices) — platform-level protections (auth, 2FA, single-tenancy, sensitive data flagging)
* [Deployment Readiness](/deployment-readiness) — performance, testing, and load-testing checklist for launch
* [Branching and Merging](/team-collaboration/branching-and-merging) — develop on non-live branches, merge deliberately
* [Data Sources](/the-database/database-basics/data-sources) — separate dev and live data
* [Sandbox](/testing-debugging/sandbox) — preview changes in an isolated copy of your workspace
* [Role-Based Access Control](/team-collaboration/role-based-access-control-rbac) — who on your team can do what
* [Security Policy](/xano-features/instance-settings/security-policy) — instance-level enforcement (2FA, SSO, IP rules)
* [Audit Logs](/xano-features/workspace-settings/audit-logs) — workspace activity history
* [Backup and Restore](/xano-features/instance-settings/backup-and-restore) — manual backups and retention
* [APIs](/the-function-stack/building-with-visual-development/apis) — endpoint settings reference
* [Request History](/maintenance-monitoring-and-logging/request-history) — auditing incoming traffic
