diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2d661c..9d83437 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## 0.5.3
+
+### New features
+
+- Allow `default: nil` to be used without needing `required: false` for the
+  `OptionsDeclaration.option` method.
+
 ## 0.5.2
 
 ### New features
diff --git a/Gemfile.lock b/Gemfile.lock
index 4d2e7ce..1881b85 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,7 +1,7 @@
 PATH
   remote: .
   specs:
-    stimpack (0.5.2)
+    stimpack (0.5.3)
       activesupport (~> 6.1)
 
 GEM
diff --git a/lib/stimpack/options_declaration.rb b/lib/stimpack/options_declaration.rb
index f58dbf7..965c4e7 100644
--- a/lib/stimpack/options_declaration.rb
+++ b/lib/stimpack/options_declaration.rb
@@ -53,7 +53,7 @@ def self.extended(klass)
       #     option :user
       #   end
       #
-      def option(*identifiers, required: true, default: nil, private_reader: true) # rubocop:disable Metrics/MethodLength
+      def option(*identifiers, required: true, default: Option::MISSING_VALUE, private_reader: true) # rubocop:disable Metrics/MethodLength
         self.options_configuration = options_configuration.merge(
           identifiers.map do |identifier|
             [
@@ -87,6 +87,10 @@ def required_options
       def optional_options
         options_configuration.select { |_, option| option.optional? }.keys
       end
+
+      def default_options
+        options_configuration.select { |_, option| option.default? }.keys
+      end
     end
 
     # Injects an initializer that assigns options and proxies the call to any
@@ -146,25 +150,37 @@ def self.included(klass)
     end
 
     class Option
+      MISSING_VALUE = "__missing__"
+
       def initialize(name, required:, default:)
         @name = name
         @default = default
         @required = required
       end
 
-      attr_reader :name, :default, :required
+      attr_reader :name
 
       def default_value
+        return nil unless default?
+
         default.respond_to?(:call) ? default.() : default
       end
 
       def required?
-        required && default.nil?
+        required && !default?
       end
 
       def optional?
         !required?
       end
+
+      def default?
+        default != MISSING_VALUE
+      end
+
+      private
+
+      attr_reader :default, :required
     end
   end
 end
diff --git a/lib/stimpack/version.rb b/lib/stimpack/version.rb
index 345703a..e243e1e 100644
--- a/lib/stimpack/version.rb
+++ b/lib/stimpack/version.rb
@@ -1,5 +1,5 @@
 # frozen_string_literal: true
 
 module Stimpack
-  VERSION = "0.5.2"
+  VERSION = "0.5.3"
 end
diff --git a/spec/stimpack/options_declaration_spec.rb b/spec/stimpack/options_declaration_spec.rb
index b4081d2..d2c6d8f 100644
--- a/spec/stimpack/options_declaration_spec.rb
+++ b/spec/stimpack/options_declaration_spec.rb
@@ -13,12 +13,13 @@
       option :bar, required: false
       option :baz, private_reader: false
       option :qux, default: "Foo"
+      option :quuz, default: nil
       option :quux, default: -> { "Bar" }
     end
   end
 
   describe ".option" do
-    it { expect(service.options_configuration.size).to eq(5) }
+    it { expect(service.options_configuration.size).to eq(6) }
     it { expect(service.options_configuration.values).to all(be_a(described_class::Option)) }
 
     describe "private_reader (option)" do
@@ -26,12 +27,12 @@
       let(:private_instance_methods) { service.private_instance_methods(false) }
 
       it { expect(public_instance_methods).to contain_exactly(:baz) }
-      it { expect(private_instance_methods).to contain_exactly(:foo, :bar, :qux, :quux) }
+      it { expect(private_instance_methods).to contain_exactly(:foo, :bar, :qux, :quux, :quuz) }
     end
   end
 
   describe ".options" do
-    it { expect(service.options).to contain_exactly(:foo, :bar, :baz, :qux, :quux) }
+    it { expect(service.options).to contain_exactly(:foo, :bar, :baz, :qux, :quux, :quuz) }
   end
 
   describe ".required_options" do
@@ -39,7 +40,11 @@
   end
 
   describe ".optional_options" do
-    it { expect(service.optional_options).to contain_exactly(:bar, :qux, :quux) }
+    it { expect(service.optional_options).to contain_exactly(:bar, :qux, :quux, :quuz) }
+  end
+
+  describe ".default_options" do
+    it { expect(service.default_options).to contain_exactly(:qux, :quux, :quuz) }
   end
 
   describe "#initialize" do
@@ -86,6 +91,7 @@
       context "when default option is assigned by omission" do
         it { expect(instance.send(:qux)).to eq("Foo") }
         it { expect(instance.send(:quux)).to eq("Bar") }
+        it { expect(instance.send(:quuz)).to eq(nil) }
       end
     end
   end