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

# Consistency

> Learn about consistency settings and versioning in LanceDB tables.

export const RsConsistencyMakeUsersReader = "fn make_users_reader(\n    ids: Vec<i64>,\n    names: Vec<&str>,\n    login_counts: Option<Vec<i64>>,\n) -> Box<dyn RecordBatchReader + Send> {\n    let mut fields = vec![\n        Field::new(\"id\", DataType::Int64, false),\n        Field::new(\"name\", DataType::Utf8, false),\n    ];\n    let mut columns: Vec<Arc<dyn Array>> =\n        vec![Arc::new(Int64Array::from(ids)), Arc::new(StringArray::from(names))];\n\n    if let Some(login_counts) = login_counts {\n        fields.push(Field::new(\"login_count\", DataType::Int64, true));\n        columns.push(Arc::new(Int64Array::from(login_counts)));\n    }\n\n    let schema = Arc::new(Schema::new(fields));\n    let batch = RecordBatch::try_new(schema.clone(), columns).unwrap();\n    let reader = RecordBatchIterator::new(vec![Ok(batch)].into_iter(), schema);\n    Box::new(reader)\n}\n";

export const RsConsistencyCheckoutLatest = "let checkout_writer_db = connect(&db_uri).execute().await.unwrap();\nlet checkout_reader_db = connect(&db_uri).execute().await.unwrap();\nlet checkout_writer_table = checkout_writer_db\n    .create_table(\n        \"consistency_checkout_latest_table\",\n        make_users_reader(vec![1], vec![\"Alice\"], None),\n    )\n    .mode(CreateTableMode::Overwrite)\n    .execute()\n    .await\n    .unwrap();\nlet checkout_reader_table = checkout_reader_db\n    .open_table(\"consistency_checkout_latest_table\")\n    .execute()\n    .await\n    .unwrap();\ncheckout_writer_table\n    .add(make_users_reader(vec![2], vec![\"Bob\"], None))\n    .execute()\n    .await\n    .unwrap();\nlet rows_before_refresh = checkout_reader_table.count_rows(None).await.unwrap();\nprintln!(\"Rows before checkout_latest: {}\", rows_before_refresh);\ncheckout_reader_table.checkout_latest().await.unwrap();\nlet rows_after_refresh = checkout_reader_table.count_rows(None).await.unwrap();\nprintln!(\"Rows after checkout_latest: {}\", rows_after_refresh);\n";

export const TsConsistencyCheckoutLatest = "const checkoutWriterDb = await lancedb.connect(databaseDir);\nconst checkoutReaderDb = await lancedb.connect(databaseDir);\nconst checkoutWriterTable = await checkoutWriterDb.createTable(\n  \"consistency_checkout_latest_table\",\n  [{ id: 1 }],\n  { mode: \"overwrite\" },\n);\nconst checkoutReaderTable = await checkoutReaderDb.openTable(\n  \"consistency_checkout_latest_table\",\n);\nawait checkoutWriterTable.add([{ id: 2 }]);\nconst rowsBeforeRefresh = await checkoutReaderTable.countRows();\nconsole.log(`Rows before checkoutLatest: ${rowsBeforeRefresh}`);\nawait checkoutReaderTable.checkoutLatest();\nconst rowsAfterRefresh = await checkoutReaderTable.countRows();\nconsole.log(`Rows after checkoutLatest: ${rowsAfterRefresh}`);\n";

export const ConsistencyCheckoutLatest = "uri = str(tmp_db.uri)\nwriter_db = lancedb.connect(uri)\nreader_db = lancedb.connect(uri)\nwriter_table = writer_db.create_table(\n    \"consistency_checkout_latest_table\", [{\"id\": 1}], mode=\"overwrite\"\n)\nreader_table = reader_db.open_table(\"consistency_checkout_latest_table\")\n\nwriter_table.add([{\"id\": 2}])\nrows_before_refresh = reader_table.count_rows()\nprint(f\"Rows before checkout_latest: {rows_before_refresh}\")\n\nreader_table.checkout_latest()\nrows_after_refresh = reader_table.count_rows()\nprint(f\"Rows after checkout_latest: {rows_after_refresh}\")\n";

export const RsConsistencyEventual = "let eventual_writer_db = connect(&db_uri).execute().await.unwrap();\nlet eventual_reader_db = connect(&db_uri)\n    .read_consistency_interval(StdDuration::from_secs(3600))\n    .execute()\n    .await\n    .unwrap();\nlet eventual_writer_table = eventual_writer_db\n    .create_table(\n        \"consistency_eventual_table\",\n        make_users_reader(vec![1], vec![\"Alice\"], None),\n    )\n    .mode(CreateTableMode::Overwrite)\n    .execute()\n    .await\n    .unwrap();\nlet eventual_reader_table = eventual_reader_db\n    .open_table(\"consistency_eventual_table\")\n    .execute()\n    .await\n    .unwrap();\neventual_writer_table\n    .add(make_users_reader(vec![2], vec![\"Bob\"], None))\n    .execute()\n    .await\n    .unwrap();\nlet eventual_rows_after_write = eventual_reader_table.count_rows(None).await.unwrap();\nprintln!(\n    \"Rows visible before eventual refresh interval: {}\",\n    eventual_rows_after_write\n);\n";

export const TsConsistencyEventual = "const eventualWriterDb = await lancedb.connect(databaseDir);\nconst eventualReaderDb = await lancedb.connect(databaseDir, {\n  readConsistencyInterval: 3600,\n});\nconst eventualWriterTable = await eventualWriterDb.createTable(\n  \"consistency_eventual_table\",\n  [{ id: 1 }],\n  { mode: \"overwrite\" },\n);\nconst eventualReaderTable = await eventualReaderDb.openTable(\n  \"consistency_eventual_table\",\n);\nawait eventualWriterTable.add([{ id: 2 }]);\nconst eventualRowsAfterWrite = await eventualReaderTable.countRows();\nconsole.log(\n  `Rows visible before eventual refresh interval: ${eventualRowsAfterWrite}`,\n);\n";

export const ConsistencyEventual = "from datetime import timedelta\n\nuri = str(tmp_db.uri)\nwriter_db = lancedb.connect(uri)\nreader_db = lancedb.connect(uri, read_consistency_interval=timedelta(seconds=3600))\nwriter_table = writer_db.create_table(\n    \"consistency_eventual_table\", [{\"id\": 1}], mode=\"overwrite\"\n)\nreader_table = reader_db.open_table(\"consistency_eventual_table\")\nwriter_table.add([{\"id\": 2}])\nrows_after_write = reader_table.count_rows()\nprint(f\"Rows visible before eventual refresh interval: {rows_after_write}\")\n";

export const RsConsistencyStrong = "let strong_writer_db = connect(&db_uri).execute().await.unwrap();\nlet strong_reader_db = connect(&db_uri)\n    .read_consistency_interval(StdDuration::from_secs(0))\n    .execute()\n    .await\n    .unwrap();\nlet strong_writer_table = strong_writer_db\n    .create_table(\n        \"consistency_strong_table\",\n        make_users_reader(vec![1], vec![\"Alice\"], None),\n    )\n    .mode(CreateTableMode::Overwrite)\n    .execute()\n    .await\n    .unwrap();\nlet strong_reader_table = strong_reader_db\n    .open_table(\"consistency_strong_table\")\n    .execute()\n    .await\n    .unwrap();\nstrong_writer_table\n    .add(make_users_reader(vec![2], vec![\"Bob\"], None))\n    .execute()\n    .await\n    .unwrap();\nlet strong_rows_after_write = strong_reader_table.count_rows(None).await.unwrap();\nprintln!(\n    \"Rows visible with strong consistency: {}\",\n    strong_rows_after_write\n);\n";

export const TsConsistencyStrong = "const strongWriterDb = await lancedb.connect(databaseDir);\nconst strongReaderDb = await lancedb.connect(databaseDir, {\n  readConsistencyInterval: 0,\n});\nconst strongWriterTable = await strongWriterDb.createTable(\n  \"consistency_strong_table\",\n  [{ id: 1 }],\n  { mode: \"overwrite\" },\n);\nconst strongReaderTable = await strongReaderDb.openTable(\n  \"consistency_strong_table\",\n);\nawait strongWriterTable.add([{ id: 2 }]);\nconst strongRowsAfterWrite = await strongReaderTable.countRows();\nconsole.log(`Rows visible with strong consistency: ${strongRowsAfterWrite}`);\n";

export const ConsistencyStrong = "from datetime import timedelta\n\nuri = str(tmp_db.uri)\nwriter_db = lancedb.connect(uri)\nreader_db = lancedb.connect(uri, read_consistency_interval=timedelta(0))\nwriter_table = writer_db.create_table(\n    \"consistency_strong_table\", [{\"id\": 1}], mode=\"overwrite\"\n)\nreader_table = reader_db.open_table(\"consistency_strong_table\")\nwriter_table.add([{\"id\": 2}])\nrows_after_write = reader_table.count_rows()\nprint(f\"Rows visible with strong consistency: {rows_after_write}\")\n";

You can set `read_consistency_interval` on the connection to control how often reads check for updates from other writers.

There are three possible settings for `read_consistency_interval` when working with [LanceTable](/tables-and-namespaces#understanding-tables):

1. **Unset (default)**: no automatic cross-process refresh checks.
2. **Zero seconds**: check for updates on every read (strongest freshness).
3. **Non-zero interval**: check for updates after the interval elapses (eventual refresh).

The value you set depends on your application's consistency needs and performance requirements.
For example, a real-time dashboard might require strong consistency, while a batch analytics job might be
fine with eventual consistency.

<Callout color="red">
  **Consistency in Remote Tables**

  In LanceDB <Badge color="red">Enterprise</Badge> (where you use `RemoteTable`), consistency is deployment-configured
  (via a `weak_read_consistency_interval_seconds` parameter in the cluster setup), and is not an end-user setting in the SDK.
  You can still use `checkout_latest` / `checkoutLatest` for explicit manual refresh.
</Callout>

## Configure Consistency Parameters

To set strong consistency, set the interval to 0:

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {ConsistencyStrong}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsConsistencyStrong}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsConsistencyStrong}
  </CodeBlock>
</CodeGroup>

<Expandable title="In the Rust snippets, a `make_users_reader` helper is used to build Arrow input data.">
  <CodeGroup>
    <CodeBlock filename="Rust" language="Rust" icon="rust">
      {RsConsistencyMakeUsersReader}
    </CodeBlock>
  </CodeGroup>
</Expandable>

For eventual consistency, use a non-zero interval:

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {ConsistencyEventual}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsConsistencyEventual}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsConsistencyEventual}
  </CodeBlock>
</CodeGroup>

With the default unset interval, tables do not auto-refresh from other writers.
To manually check for updates, use `checkout_latest` / `checkoutLatest`:

<CodeGroup>
  <CodeBlock filename="Python" language="Python" icon="python">
    {ConsistencyCheckoutLatest}
  </CodeBlock>

  <CodeBlock filename="TypeScript" language="TypeScript" icon="square-js">
    {TsConsistencyCheckoutLatest}
  </CodeBlock>

  <CodeBlock filename="Rust" language="Rust" icon="rust">
    {RsConsistencyCheckoutLatest}
  </CodeBlock>
</CodeGroup>

## Handle bad vectors

<Note>
  This section is currently specific to the Python SDK.
</Note>

In LanceDB Python, you can use the `on_bad_vectors` parameter to choose how
invalid vector values are handled. Invalid vectors are vectors that are not valid
because:

1. They are the wrong dimension
2. They contain NaN values
3. They are null but are on a non-nullable field

By default, LanceDB will raise an error if it encounters a bad vector. You can
also choose one of the following options:

* `drop`: Ignore rows with bad vectors
* `fill`: Replace bad values (NaNs) or missing values (too few dimensions) with
  the fill value specified in the `fill_value` parameter. An input like
  `[1.0, NaN, 3.0]` will be replaced with `[1.0, 0.0, 3.0]` if `fill_value=0.0`.
* `null`: Replace bad vectors with null (only works if the column is nullable).
  A bad vector `[1.0, NaN, 3.0]` will be replaced with `null` if the column is
  nullable. If the vector column is non-nullable, then bad vectors will cause an
  error
