rubyguides

Kernel#sleep

sleep([duration]) -> integer or nil

Kernel#sleep suspends the current thread’s execution for the specified number of seconds. If no duration is given, it sleeps indefinitely until interrupted. Returns the number of seconds actually slept, or nil if interrupted by a signal.

Syntax

sleep(duration)
sleep

The two forms are simple: pass a number to pause for that many seconds, or pass nothing to sleep indefinitely until a signal arrives. Ruby stores the duration as a Numeric, so you can use integers for whole seconds or floats for sub-second precision without any special configuration.

Parameters

ParameterTypeDefaultDescription
durationNumericnilNumber of seconds to sleep. Can be fractional for sub-second precision. If nil or omitted, sleeps indefinitely.

Examples

Basic usage

puts "Starting"
sleep(2)
puts "Woke up after 2 seconds"
# Starting
# Woke up after 2 seconds

The simplest form of sleep takes an integer argument and pauses for exactly that many seconds. This is the form you reach for when a script needs to wait for a fixed amount of time — between retries, before reading a file that another process is writing, or to pace a sequence of printed messages so they are readable.

Sleeping for fractional seconds

start = Time.now
sleep(0.5)  # sleep for 500 milliseconds
puts Time.now - start
# => 0.5

Ruby accepts fractional seconds as a Float, so sub-second precision is available without any special configuration. The actual sleep duration may be slightly longer than requested due to operating system scheduling, but for most timing tasks — rate limiting, polling, animation pacing — the difference is too small to matter.

Sleeping indefinitely

# This runs until interrupted
sleep

An indefinite sleep with no argument puts the thread to rest until a signal arrives, which is useful in daemon processes or scripts that wait for an external trigger. Without a duration, the call blocks forever, so this form should only appear in code that expects to be woken by a signal handler or an interrupt.

Using sleep in a loop

5.times do |i|
  puts "Count: #{i}"
  sleep(1)
end
# Count: 0
# Count: 1
# Count: 2
# Count: 3
# Count: 4

A one-second pause inside a counting loop creates a visible rhythm that makes the output easy to follow in the terminal. In real applications, the delay would usually be shorter or driven by an external event, but the structure is the same: the loop body does work, then sleep yields control before the next iteration begins.

Common Patterns

Polling interval

def poll_until(condition, interval: 1, timeout: 30)
  elapsed = 0
  while elapsed < timeout
    return yield if yield
    sleep(interval)
    elapsed += interval
  end
  nil
end

# Usage: wait for a file to exist
poll_until { File.exist?('/tmp/ready') }

Polling with sleep avoids busy-waiting, which would spin the CPU at full speed while checking a condition that changes only occasionally. The interval gives the external resource time to become ready and keeps the CPU load low. The timeout parameter adds a safety net so the loop cannot run forever if the condition never becomes true.

Rate limiting

requests = ['req1', 'req2', 'req3']

requests.each do |req|
  process(req)
  sleep(0.5)  # rate limit to 2 requests per second
end

Retry with backoff

When a transient failure is likely to clear after a short wait, exponential backoff is a safer strategy than hammering the failing service at a fixed interval. Each retry doubles the delay, giving the remote system breathing room while the local code keeps trying:

def retry_with_backoff(max_attempts: 3)
  attempt = 0
  begin
    attempt += 1
    yield
  rescue => e
    if attempt < max_attempts
      sleep(2 ** attempt)  # 2, 4, 8 seconds
      retry
    else
      raise e
    end
  end
end

Errors

  • ArgumentError: Raised if duration is negative.
  • ThreadError: May be raised if sleeping while the thread is being killed.

pausing with a clear purpose

sleep is most useful when the pause itself is part of the behavior, such as polling, simple retries, or pacing a loop so it does not run too fast. The code should make that reason visible, because an unexplained pause can look like a bug. Keeping the delay small and intentional makes it easier to test and easier to remove later if the timing strategy changes. That is especially true in scripts that only need to wait long enough for the next step to be ready.

The method also pairs well with loops that need to check for a condition without using busy waiting. A short pause can give a resource time to appear, give a background task time to finish, or give the user a moment before the next retry. The important part is that the wait belongs to the task, not just to the code style. When the reason is clear, sleep reads like part of the plan instead of a mystery delay.

It is also worth keeping the duration visible near the logic that depends on it. That way the reader can tell whether the pause is a tiny pacing step or a more deliberate wait. If the timing starts to spread across several methods, it can become hard to tell why the code is idle. A simple, local pause is easier to explain and easier to change when the task no longer needs it.

See Also