# Best Practices

## Do not force a response format while chaining

By default an operation returns the result in whatever form it produced, and the server converts nothing. Keep that default for every intermediate result: the Term goes straight into the next call, so a conversion there is time spent on a format nothing reads. Ask for `regex` only on the last call, when the result has to be displayed or stored as a pattern. See [Term's Format](/core-concepts/terms-format).

## Reuse Terms to avoid redundant calls

A Term caches the results of the analysis operations that take a single Term (cardinality, length, pattern, empty, totality, and so on). Calling one of those again on the **same Term instance** returns the cached value instead of calling the API. Comparisons between two Terms, `equivalent` and `subset`, are not cached and always cost a request.

This means it is worth keeping a reference to a Term and reusing it, rather than recreating it from the same pattern or FAIR value every time.

<CodeTabs defaultValue="java">
<CodeTabs.Tab value="java" label="Java">
```java
RegexSolverClient client = RegexSolverClient.builder()
    .apiToken(System.getenv("REGEXSOLVER_API_TOKEN"))
    .build();

Term term = Term.regex("(abc|de){2}");

// First call hits the API and caches the result on `term`
Cardinality cardinality = client.getCardinality(term);

// Second call on the same instance returns the cached value
Cardinality cardinalityAgain = client.getCardinality(term);
```
</CodeTabs.Tab>

<CodeTabs.Tab value="javascript" label="JavaScript">
```javascript
const client = new RegexSolverClient({ apiToken: process.env.REGEXSOLVER_API_TOKEN });

const term = Term.regex("(abc|de){2}");

// First call hits the API and caches the result on `term`
const cardinality = await client.getCardinality(term);

// Second call on the same instance returns the cached value
const cardinalityAgain = await client.getCardinality(term);
```
</CodeTabs.Tab>

<CodeTabs.Tab value="python" label="Python">
```python
client = RegexSolverClient(api_token=os.getenv("REGEXSOLVER_API_TOKEN"))

term = Term.regex(r"(abc|de){2}")

# First call hits the API and caches the result on `term`
cardinality = client.get_cardinality(term)

# Second call on the same instance returns the cached value
cardinality_again = client.get_cardinality(term)
```
</CodeTabs.Tab>
</CodeTabs>

## Lower the execution timeout for unpredictable patterns

Every operation already runs under a timeout: when you do not set one, the server applies the maximum your plan allows. Setting `executionTimeout` yourself lowers that ceiling for a single call. This is worth doing when you process patterns coming from user input, or patterns whose complexity you cannot predict, and you want them to fail faster than the plan maximum so your own request stays responsive. See [Bounding Execution](/advance-usage/bounding-execution).

## Split heavy operations from pattern generation

The operation and the conversion of its result to a regex pattern share a single time budget. When a heavy operation leaves little of that budget behind, the pattern that comes back is correct but harder to read. Ask for FAIR on the heavy call and fetch the pattern in a second call, which gets a full budget of its own. See [Heavy Operations](/advance-usage/heavy-operations).

## Mind determinism when paginating generated strings

If you generate strings page by page using an offset, make sure the Term's automaton is deterministic first. Otherwise, the order of the results may change between calls and pagination can skip or repeat strings. See [Determinism](/advance-usage/determinism).
