diff --git a/internal/arduino/builder/internal/compilation/database.go b/internal/arduino/builder/internal/compilation/database.go
index 73441bc07bc..9498b5a9e81 100644
--- a/internal/arduino/builder/internal/compilation/database.go
+++ b/internal/arduino/builder/internal/compilation/database.go
@@ -19,6 +19,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"os"
+	"sync"
 
 	"github.com/arduino/arduino-cli/internal/i18n"
 	"github.com/arduino/go-paths-helper"
@@ -28,8 +29,9 @@ var tr = i18n.Tr
 
 // Database keeps track of all the compile commands run by the builder
 type Database struct {
-	Contents []Command
-	File     *paths.Path
+	lock     sync.Mutex
+	contents []Command
+	file     *paths.Path
 }
 
 // Command keeps track of a single run of a compile command
@@ -43,8 +45,8 @@ type Command struct {
 // NewDatabase creates an empty CompilationDatabase
 func NewDatabase(filename *paths.Path) *Database {
 	return &Database{
-		File:     filename,
-		Contents: []Command{},
+		file:     filename,
+		contents: []Command{},
 	}
 }
 
@@ -55,16 +57,18 @@ func LoadDatabase(file *paths.Path) (*Database, error) {
 		return nil, err
 	}
 	res := NewDatabase(file)
-	return res, json.Unmarshal(f, &res.Contents)
+	return res, json.Unmarshal(f, &res.contents)
 }
 
 // SaveToFile save the CompilationDatabase to file as a clangd-compatible compile_commands.json,
 // see https://clang.llvm.org/docs/JSONCompilationDatabase.html
 func (db *Database) SaveToFile() {
-	if jsonContents, err := json.MarshalIndent(db.Contents, "", " "); err != nil {
+	db.lock.Lock()
+	defer db.lock.Unlock()
+	if jsonContents, err := json.MarshalIndent(db.contents, "", " "); err != nil {
 		fmt.Println(tr("Error serializing compilation database: %s", err))
 		return
-	} else if err := db.File.WriteFile(jsonContents); err != nil {
+	} else if err := db.file.WriteFile(jsonContents); err != nil {
 		fmt.Println(tr("Error writing compilation database: %s", err))
 	}
 }
@@ -88,5 +92,7 @@ func (db *Database) Add(target *paths.Path, command *paths.Process) {
 		File:      target.String(),
 	}
 
-	db.Contents = append(db.Contents, entry)
+	db.lock.Lock()
+	db.contents = append(db.contents, entry)
+	db.lock.Unlock()
 }
diff --git a/internal/arduino/builder/internal/compilation/database_test.go b/internal/arduino/builder/internal/compilation/database_test.go
index abe5b7b24b9..dde90738d91 100644
--- a/internal/arduino/builder/internal/compilation/database_test.go
+++ b/internal/arduino/builder/internal/compilation/database_test.go
@@ -36,11 +36,11 @@ func TestCompilationDatabase(t *testing.T) {
 	db2, err := LoadDatabase(tmpfile)
 	require.NoError(t, err)
 	require.Equal(t, db, db2)
-	require.Len(t, db2.Contents, 1)
-	require.Equal(t, db2.Contents[0].File, "test")
-	require.Equal(t, db2.Contents[0].Command, "")
-	require.Equal(t, db2.Contents[0].Arguments, []string{"gcc", "arg1", "arg2"})
+	require.Len(t, db2.contents, 1)
+	require.Equal(t, db2.contents[0].File, "test")
+	require.Equal(t, db2.contents[0].Command, "")
+	require.Equal(t, db2.contents[0].Arguments, []string{"gcc", "arg1", "arg2"})
 	cwd, err := paths.Getwd()
 	require.NoError(t, err)
-	require.Equal(t, db2.Contents[0].Directory, cwd.String())
+	require.Equal(t, db2.contents[0].Directory, cwd.String())
 }