diff --git a/generic_executor.go b/generic_executor.go
new file mode 100644
index 0000000..9bf1a1a
--- /dev/null
+++ b/generic_executor.go
@@ -0,0 +1,60 @@
+package goload
+
+import (
+	"context"
+	"time"
+)
+
+type genericExecutor struct {
+	name    string
+	handler func(ctx context.Context) error
+	options *ExecutorOptions
+}
+
+type ExecutorOption func(options *ExecutorOptions)
+
+func WithWeight(weight int) ExecutorOption {
+	return func(options *ExecutorOptions) {
+		options.Weight = weight
+	}
+}
+
+func WithTimeout(timeout time.Duration) ExecutorOption {
+	return func(options *ExecutorOptions) {
+		options.Timeout = timeout
+	}
+}
+
+func NewGenericExecutor(name string, handler func(ctx context.Context) error, opts ...ExecutorOption) Executor {
+	options := &ExecutorOptions{
+		Weight:  1,
+		Timeout: 0,
+	}
+
+	for _, opt := range opts {
+		opt(options)
+	}
+
+	return &genericExecutor{
+		name:    name,
+		handler: handler,
+		options: options,
+	}
+}
+
+func (d *genericExecutor) Execute(ctx context.Context) ExecutionResponse {
+	err := d.handler(ctx)
+	return ExecutionResponse{
+		Identifier:     d.Name(),
+		Err:            err,
+		AdditionalData: nil,
+	}
+}
+
+func (d *genericExecutor) Name() string {
+	return d.name
+}
+
+func (d *genericExecutor) Options() *ExecutorOptions {
+	return d.options
+}
diff --git a/runner.go b/runner.go
index 4ed5d8b..e19dbf1 100644
--- a/runner.go
+++ b/runner.go
@@ -162,7 +162,7 @@ func (r *Runner) hit(ex Executor, began time.Time) *Result {
 		defer cancel()
 	} else if r.defaultTimeout > 0 {
 		var cancel context.CancelFunc
-		ctx, cancel = context.WithTimeout(context.Background(), ex.Options().Timeout)
+		ctx, cancel = context.WithTimeout(context.Background(), r.defaultTimeout)
 		defer cancel()
 	}