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

# FAQ

### When should I use browser pools vs. creating browsers on-demand?

Use browser pools when you need to run many browsers concurrently (50+ simultaneous browsers). Pools allow you to pre-configure a set of browsers for your use case, enabling you to scale to hundreds or thousands of concurrent browser sessions.

### How do I know if my pool is too small or too large?

Monitor the `available_count` metric. If it frequently drops to 0, your pool is too small. If it stays above 30-40% of the pool size during normal operation, you're over-provisioned. Target 10-20% available browsers during typical load.

### What happens if I don't release a browser back to the pool?

The browser will remain "acquired" until the idle timeout expires, at which point it's destroyed and a new browser is created to refill the pool. Unreleased browsers create inefficiency and can exhaust your pool.

### What is `fill_rate_per_minute`?

`fill_rate_per_minute` is the percentage of the pool that will be refilled per minute. For example, if you set `fill_rate_per_minute` to 10, the pool will be refilled with 10% of the pool size per minute.

When a browser from a pool is set to be destroyed (by reaching its specified `timeout_seconds` or `reuse: false`), a pool refill will be triggered to replace any destroyed browsers with new ones. Refill checks run once per minute.

### Can I update a pool's configuration without recreating it?

Yes, use `kernel.browserPools.update()`. By default (`discard_all_idle: false`), existing idle browsers keep their current configuration and only newly created browsers use the new one. Pass `discard_all_idle: true` to discard all idle browsers and rebuild them immediately with the new configuration.

### If I update a pool, do browsers that are currently in use pick up the new configuration?

No. A plain `update()` doesn't rebuild any existing browsers — it only changes the configuration used for future ones. Even the idle browsers keep their old config unless you pass `discard_all_idle: true` (or flush the pool). Browsers that are acquired during the update are never touched regardless: an in-use browser keeps its original configuration, and if you release it with `reuse: true` (the default) it returns to the pool still running the old configuration and keeps getting handed out that way.

You have three ways to get it onto the new configuration: release it with `reuse: false` so it's destroyed and rebuilt on release instead of the old one returning to the pool; let the acquired browser reach its `timeout_seconds` while idle so it's destroyed and the pool refills automatically; or flush it after the fact with `kernel.browserPools.flush()` (or a later `kernel.browserPools.update()` with `discard_all_idle: true`) once the in-use browsers have been released.

### If I update a profile's contents, will my pool's idle browsers pick up the change?

By default, yes — `refresh_on_profile_update` is automatically set to `true` when a pool is created with a profile or when the pool's profile is changed. Idle browsers are flushed whenever the profile is saved, so they get replaced with fresh ones using the updated profile.

If you've explicitly disabled `refresh_on_profile_update`, you can still force the pool to pick up new profile contents:

* **Manual**: Call `kernel.browserPools.flush()` to destroy idle browsers (the pool refills automatically), or call `kernel.browserPools.update()` with `discard_all_idle: true`. See [Refresh on profile update](/docs/browsers/pools/overview#refresh-on-profile-update).

### Can pooled browsers save changes back to a profile?

Not at the pool level, but yes per session. These are two different things:

* **A profile set on the pool config** is loaded read-only. Every browser in the pool shares it and would try to save concurrently, so `save_changes` does not apply to pools — sending it on a pool's profile is silently ignored (not rejected). This is by design: it prevents profile corruption and the ambiguity of which idle browser's state would "win".
* **A profile attached to a single browser *after* you acquire it** does persist. Create the pool with no profile, acquire a browser, attach a per-user profile with `save_changes: true` via `kernel.browsers.update()`, then release with `reuse: false` so the browser is destroyed (which flushes the profile) instead of returning to the pool.

The second pattern is the recommended way to load many per-user profiles through a pool's pre-warmed browsers — see [Per-user profiles with pools](/docs/browsers/pools/overview#per-user-profiles-with-pools).

### Should I set `reuse: true` or `reuse: false` when releasing?

Use `reuse: true` (default) for efficiency. Only use `reuse: false` when you suspect browser state corruption or need a guaranteed clean browser session.

### How do pool timeouts interact with task duration?

The pool's `timeout_seconds` only applies while the browser is acquired. If your task takes 5 minutes and timeout is 3 minutes, the browser won't be destroyed—the timeout only triggers if the browser is idle (no CDP connection) for 3 minutes.

### Can I use different browser configurations within the same pool?

All browsers in a pool initialize with the same configuration. Calling `kernel.browserPools.update()` changes the pool's configuration for browsers created after the update; existing idle browsers keep their original configuration unless you pass `discard_all_idle: true` (or flush the pool).
Once you've acquired a browser, you can apply certain [hot swap configurations](https://www.kernel.sh/docs/api-reference/browsers/update-browser-session) to that browser instance using `kernel.browsers.update()`.

### How do I handle rate limiting from target websites?

* Implement delays between requests
* Use multiple proxy pools to distribute requests across IPs
* Implement backoff when rate limits are detected
* Consider creating separate pools with different proxy configurations

### What's the best way to debug issues in production?

* Use `headless: false` for a temporary debug pool, access `browser_live_view_url` to watch browser sessions in real-time
* Collect screenshots at error points, and maintain detailed logging around acquire/release operations
* Monitor past sessions via [replays](/docs/browsers/replays).
