What is LockService in Google Sheets Apps Script?

LockService gives your script a mutex so only one execution holds a lock at a time. In busy spreadsheets, two triggers firing together can both read the same last row and write duplicates. LockService.waitLock and releaseLock serialize critical sections like appendRow, counter increments, or quota-sensitive API calls.

When to use it

Use LockService when parallel runs are possible: dual form submits, overlapping time triggers, onEdit plus manual menu running together, or any shared counter and log append pattern.

When to skip it

Skip locks for read-only work or single-threaded manual runs. Over-locking everything slows the script and can cause wait timeouts if one run hangs.

How it works

  1. 1

    const lock = LockService.getScriptLock() for project-wide coordination.

  2. 2

    lock.waitLock(30000) waits up to 30 seconds to acquire the lock.

  3. 3

    Wrap the critical section in try/finally and call lock.releaseLock() in finally.

  4. 4

    {:"Keep locked sections short"=>"read, compute, write, then release."}

  5. 5

    Document lock and user lock exist for narrower scopes when appropriate.

  6. 6

    Log when waitLock times out so you know contention is too high.

Examples in Google Sheets

Safe appendRow

onFormSubmit waits for lock, appendRow to Log, increments Script Properties ticket counter, then releases lock in finally.

Shared invoice number

Two sales triggers read max invoice id, increment, and write back. Lock prevents duplicate invoice numbers.

API rate guard

Only one execution at a time calls a strict external API, avoiding parallel UrlFetchApp bursts.

Build this without starting from a blank cell

Use a Better Sheets tool for LockService, then watch a walkthrough when you want the full pattern.

Better Sheets resources

Common mistakes

  • Forgetting releaseLock in finally, blocking all future runs until timeout.
  • Holding a lock during long UrlFetchApp or MailApp calls, stalling every other trigger.
  • Using getUserLock when all triggers share one script account and need Script lock.
  • waitLock with zero timeout, failing instantly under normal contention.
  • Nested locks across functions without a clear order, risking deadlocks in complex projects.

Frequently asked questions

What happens if waitLock times out?
It throws an exception. Catch it, log, and decide whether to retry or alert an admin.
Do I always need LockService for appendRow?
Low-traffic sheets often work without it. High concurrency form or webhook intake benefits strongly.
What is the difference between script and document lock?
Script lock coordinates across the whole Apps Script project. Document lock scopes to one spreadsheet file.
Can simple onEdit use locks?
Yes, if the handler does restricted work in an installable trigger. Keep the locked section minimal.
Does lock work across spreadsheet copies?
No. Each file and script project has its own lock namespace.
How long can a lock be held?
Until releaseLock or the execution ends. Long runs block others for the whole wait window.
Can two different functions share one lock?
Yes. getScriptLock returns the same mutex for the project when you use the same lock type.
Is LockService related to Sheet protected ranges?
No. Protected ranges are UI permissions. LockService is runtime concurrency control in Apps Script.

Related Tutorials

Watch how LockService works

Browse more tutorials
Lock Your Sheets with OnlySheets

Lock Your Sheets with OnlySheets

Understand what you can do, if you use OnlySheets between your payment p...
Create an Internal Google Sheets Add-on

Create an Internal Google Sheets Add-on

The entire process to create and publish a Google Sheets Add-on internal...

Related glossary terms

Done reading about LockService?

Membership unlocks 636+ tutorials, unlimited generators, and every template. Practical lessons. Zero fluff.

Need this once

Jump to a free tool or a single tutorial for this topic.

Learning Sheets for real

Unlock the full library, generators, and templates with membership.