# Security and production use (/docs/core/reference/security)



Type-safe queries help prevent malformed SOQL. They do not replace OAuth,
Salesforce permissions, application authorization, or input validation.

## Keep credentials out of client code [#keep-credentials-out-of-client-code]

Keep Salesforce access tokens, refresh tokens, client secrets, and signing keys
inside an appropriate server-side or build-time secret boundary. Do not put them
in browser bundles, generated schemas, committed `.env` files, or public Vite
environment variables.

For connection options, see [authentication](/docs/rest/authentication) and the
[`@kysoql/auth` flows](/docs/auth/flows).

## Pass values through the builder [#pass-values-through-the-builder]

Keep dynamic values in builder value positions:

```ts
import { db } from "./db";

export function findAccounts(prefix: string) {
  return db
    .selectFrom("Account")
    .select(["Id", "Name"])
    .where("Name", "like", `${prefix}%`)
    .limit(50);
}
```

Kysoql serializes those values as SOQL literals and validates identifiers and
query structure. `compile().soql` contains the final escaped literals. This is
not SQL-style placeholder binding.

If `%` and `_` should be treated as literal characters in a `LIKE` value, use
`soql.likeLiteral(value)`.

Avoid concatenating user input into compiled SOQL. `soql.raw()` intentionally
bypasses normal structural protections and should only contain application-owned,
trusted syntax.

## Treat filters as authorization-sensitive [#treat-filters-as-authorization-sensitive]

A syntactically valid field or filter is not automatically safe for every caller.
Validate any user-selectable fields, operators, sort keys, list sizes, and limits
against a small application allowlist.

Also remember that `clearWhere()` removes every predicate. If a `WHERE` clause
contains a tenant or ownership boundary, do not casually clear it while composing
a request.

## Let Salesforce enforce access [#let-salesforce-enforce-access]

Generated metadata reflects the identity used during generation. It does not
guarantee that the current runtime user can still see the same rows or fields.
Salesforce remains responsible for sharing, CRUD/FLS, org configuration, and
execution-context rules.

For Apex output, choose `WITH USER_MODE` or `WITH SYSTEM_MODE` intentionally as
part of the Apex application's security design. Kysoql does not decide which mode
is appropriate for you.

## Keep result exposure intentional [#keep-result-exposure-intentional]

Only select fields the caller actually needs. This matters even when Salesforce
allows the integration identity to see more.

A few practical defaults help:

* prefer explicit field selections for API responses
* keep query limits and pagination budgets bounded
* avoid logging access tokens or full SOQL when literals may contain sensitive data
* review generated schemas before publishing them because object and field names can reveal internal structure
* use a dedicated integration identity with the minimum access needed for the job

## Retry narrowly [#retry-narrowly]

The native REST auth-provider path can refresh and replay a request after a
provider-backed `401 INVALID_SESSION_ID`. Do not turn arbitrary Salesforce or
network errors into broad automatic retries, especially for queries with
observable tracking behaviour such as `FOR VIEW` or Knowledge `UPDATE` clauses.

For transport limits and cancellation, see [REST execution](/docs/rest/execution).
For the builder's supported query boundaries, see [limitations](/docs/core/reference/limitations).
