diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py
index ef55976..586014b 100644
--- a/sqlite_utils/db.py
+++ b/sqlite_utils/db.py
@@ -6,6 +6,8 @@ import itertools
 import json
 import pathlib
 
+SQLITE_MAX_VARS = 999
+
 try:
     import numpy as np
 except ImportError:
@@ -848,7 +850,17 @@ class Table:
         ), "Use either ignore=True or upsert=True, not both"
         all_columns = None
         first = True
-        for chunk in chunks(records, batch_size):
+        # We can only handle a max of 999 variables in a SQL insert, so
+        # we need to adjust the batch_size down if we have too many cols
+        records = iter(records)
+        # Peek at first record to count its columns:
+        first_record = next(records)
+        num_columns = len(first_record.keys())
+        assert (
+            num_columns <= SQLITE_MAX_VARS
+        ), "Rows can have a maximum of {} columns".format(SQLITE_MAX_VARS)
+        batch_size = max(1, min(batch_size, SQLITE_MAX_VARS // num_columns))
+        for chunk in chunks(itertools.chain([first_record], records), batch_size):
             chunk = list(chunk)
             if first:
                 if not self.exists:

diff --git a/tests/test_create.py b/tests/test_create.py
index 222a967..71b1583 100644
--- a/tests/test_create.py
+++ b/tests/test_create.py
@@ -500,6 +500,42 @@ def test_upsert_rows_alter_table(fresh_db, use_table_factory):
     ] == list(table.rows)
 
 
+def test_bulk_insert_more_than_999_values(fresh_db):
+    "Inserting 100 items with 11 columns should work"
+    fresh_db["big"].insert_all(
+        (
+            {
+                "id": i + 1,
+                "c2": 2,
+                "c3": 3,
+                "c4": 4,
+                "c5": 5,
+                "c6": 6,
+                "c7": 7,
+                "c8": 8,
+                "c8": 9,
+                "c10": 10,
+                "c11": 11,
+            }
+            for i in range(100)
+        ),
+        pk="id",
+    )
+    assert 100 == fresh_db["big"].count
+
+
+@pytest.mark.parametrize(
+    "num_columns,should_error", ((900, False), (999, False), (1000, True))
+)
+def test_error_if_more_than_999_columns(fresh_db, num_columns, should_error):
+    record = dict([("c{}".format(i), i) for i in range(num_columns)])
+    if should_error:
+        with pytest.raises(AssertionError):
+            fresh_db["big"].insert(record)
+    else:
+        fresh_db["big"].insert(record)
+
+
 @pytest.mark.parametrize(
     "columns,index_name,expected_index",
     (

"Too many SQL variables" on large inserts
Reported here: https://github.com/dogsheep/healthkit-to-sqlite/issues/9

It looks like there's a default limit of 999 variables - we need to be smart about that, maybe dynamically lower the batch size based on the number of columns.
tests/test_create.py::test_error_if_more_than_999_columns[1000-True]
tests/test_create.py::test_create_table tests/test_create.py::test_create_table_compound_primary_key tests/test_create.py::test_create_table_with_bad_defaults tests/test_create.py::test_create_table_with_defaults tests/test_create.py::test_create_table_with_bad_not_null tests/test_create.py::test_create_table_with_not_null tests/test_create.py::test_create_table_from_example[example0-expected_columns0] tests/test_create.py::test_create_table_from_example[example1-expected_columns1] tests/test_create.py::test_create_table_from_example[example2-expected_columns2] tests/test_create.py::test_create_table_from_example_with_compound_primary_keys tests/test_create.py::test_create_table_column_order[True] tests/test_create.py::test_create_table_column_order[False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification0-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification1-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification2-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification3-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification4-NoObviousTable] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification5-AssertionError] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification6-AlterError] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[True-foreign_key_specification7-AssertionError] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification0-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification1-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification2-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification3-False] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification4-NoObviousTable] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification5-AssertionError] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification6-AlterError] tests/test_create.py::test_create_table_works_for_m2m_with_only_foreign_keys[False-foreign_key_specification7-AssertionError] tests/test_create.py::test_create_error_if_invalid_foreign_keys tests/test_create.py::test_add_column[nickname-str-None-CREATE tests/test_create.py::test_add_column[dob-date-None-CREATE tests/test_create.py::test_add_column[age-int-None-CREATE tests/test_create.py::test_add_column[weight-float-None-CREATE tests/test_create.py::test_add_column[text-TEXT-None-CREATE tests/test_create.py::test_add_column[integer-INTEGER-None-CREATE tests/test_create.py::test_add_column[float-FLOAT-None-CREATE tests/test_create.py::test_add_column[blob-blob-None-CREATE tests/test_create.py::test_add_column[default_str-None-None-CREATE tests/test_create.py::test_add_column[nickname-str--CREATE tests/test_create.py::test_add_column[nickname-str-dawg's tests/test_create.py::test_add_foreign_key tests/test_create.py::test_add_foreign_key_error_if_column_does_not_exist tests/test_create.py::test_add_foreign_key_error_if_other_table_does_not_exist tests/test_create.py::test_add_foreign_key_error_if_already_exists tests/test_create.py::test_add_foreign_keys tests/test_create.py::test_add_column_foreign_key tests/test_create.py::test_add_foreign_key_guess_table tests/test_create.py::test_index_foreign_keys tests/test_create.py::test_insert_row_alter_table[True-extra_data0-expected_new_columns0] tests/test_create.py::test_insert_row_alter_table[True-extra_data1-expected_new_columns1] tests/test_create.py::test_insert_row_alter_table[True-extra_data2-expected_new_columns2] tests/test_create.py::test_insert_row_alter_table[False-extra_data0-expected_new_columns0] tests/test_create.py::test_insert_row_alter_table[False-extra_data1-expected_new_columns1] tests/test_create.py::test_insert_row_alter_table[False-extra_data2-expected_new_columns2] tests/test_create.py::test_upsert_rows_alter_table[True] tests/test_create.py::test_upsert_rows_alter_table[False] tests/test_create.py::test_bulk_insert_more_than_999_values tests/test_create.py::test_error_if_more_than_999_columns[900-False] tests/test_create.py::test_error_if_more_than_999_columns[999-False] tests/test_create.py::test_create_index[columns0-None-expected_index0] tests/test_create.py::test_create_index[columns1-None-expected_index1] tests/test_create.py::test_create_index[columns2-age_index-expected_index2] tests/test_create.py::test_create_index_unique tests/test_create.py::test_create_index_if_not_exists tests/test_create.py::test_insert_dictionaries_and_lists_as_json[data_structure0] tests/test_create.py::test_insert_dictionaries_and_lists_as_json[data_structure1] tests/test_create.py::test_insert_dictionaries_and_lists_as_json[data_structure2] tests/test_create.py::test_insert_dictionaries_and_lists_as_json[data_structure3] tests/test_create.py::test_insert_dictionaries_and_lists_as_json[data_structure4] tests/test_create.py::test_insert_thousands_using_generator tests/test_create.py::test_insert_thousands_ignores_extra_columns_after_first_100 tests/test_create.py::test_insert_ignore tests/test_create.py::test_insert_hash_id tests/test_create.py::test_create_view tests/test_create.py::test_vacuum tests/test_create.py::test_works_with_pathlib_path tests/test_create.py::test_cannot_provide_both_filename_and_memory tests/test_create.py::test_creates_id_column