V1V0 to V1 Upgrade Guide

Hatchet Go SDK Migration Guide

This guide covers migrating from Hatchet v0 to v1. v0 has since been removed and everything now runs on v1, so this page is kept for historical reference only and is no longer relevant.

This comprehensive guide covers migration paths between all three major versions of the Hatchet Go SDK:

  • V0 SDK (github.com/hatchet-dev/hatchet/pkg/client) - Original SDK
  • V1 Generics SDK (github.com/hatchet-dev/hatchet/pkg/v1) - Type-safe SDK with Go generics (deprecated)
  • V1 Reflection SDK (github.com/hatchet-dev/hatchet/sdks/go) - Current SDK with reflection-based API

The V1 engine will continue to support V0 tasks until September 30th, 2025.

Quick Start with V1 Reflection SDK (Current)

The current V1 SDK provides the cleanest API using reflection for type safety:

package mainimport (	"context"	"log"	hatchet "github.com/hatchet-dev/hatchet/sdks/go")func main() {	client, err := hatchet.NewClient()	if err != nil {		log.Fatal(err)	}	// Define input/output types	type Input struct {		Message string `json:"message"`	}	type Output struct {		Result string `json:"result"`	}	// Create a simple task	task := client.NewStandaloneTask("simple-task", func(ctx hatchet.Context, input Input) (Output, error) {		return Output{Result: "Processed: " + input.Message}, nil	})	// Start worker	worker, err := client.NewWorker("worker", hatchet.WithWorkflows(task))	if err != nil {		log.Fatal(err)	}	if err := worker.StartBlocking(context.Background()); err != nil {		log.Fatal(err)	}}

Migration Paths

From V0 SDK to V1 Reflection SDK

V0 SDK (Legacy):

package mainimport (	"log"	"github.com/hatchet-dev/hatchet/pkg/client"	v0Worker "github.com/hatchet-dev/hatchet/pkg/worker")func V0() {	c, err := client.New()	if err != nil {		log.Fatal(err)	}	worker, err := v0Worker.NewWorker(		v0Worker.WithClient(c),		v0Worker.WithName("worker"),	)	if err != nil {		log.Fatal(err)	}	err = worker.RegisterWorkflow(		&v0Worker.WorkflowJob{			On:   v0Worker.Event("user:create"),			Name: "simple-workflow",			Steps: []*v0Worker.WorkflowStep{				{					Name: "step1",					Function: func(ctx v0Worker.HatchetContext) error {						log.Println("executed step1")						return nil					},				},			},		},	)	if err != nil {		log.Fatal(err)	}}

V1 Reflection SDK (Current):

package mainimport (	"log"	"strings"	hatchet "github.com/hatchet-dev/hatchet/sdks/go")type SimpleInput struct {	Message string `json:"message"`}type SimpleResult struct {	TransformedMessage string `json:"result"`}func V1() {	client, err := hatchet.NewClient()	if err != nil {		log.Fatal(err)	}	workflow := client.NewStandaloneTask("simple-workflow", func(ctx hatchet.Context, input SimpleInput) (SimpleResult, error) {		log.Println("executed step1")		return SimpleResult{TransformedMessage: strings.ToLower(input.Message)}, nil	}, hatchet.WithWorkflowEvents("user:create"))	_, err = client.NewWorker(		"worker",		hatchet.WithWorkflows(workflow),	)	if err != nil {		log.Fatal(err)	}}

From V1 Generics SDK to V1 Reflection SDK

V1 Generics SDK (Deprecated):

package mainimport (	"log"	"strings"	"github.com/hatchet-dev/hatchet/pkg/client/create"	v1 "github.com/hatchet-dev/hatchet/pkg/v1"	"github.com/hatchet-dev/hatchet/pkg/v1/factory"	"github.com/hatchet-dev/hatchet/pkg/v1/worker"	"github.com/hatchet-dev/hatchet/pkg/v1/workflow"	v0Worker "github.com/hatchet-dev/hatchet/pkg/worker")func V1Old() {	hatchet, err := v1.NewHatchetClient()	if err != nil {		log.Fatal(err)	}	simple := factory.NewTask(		create.StandaloneTask{Name: "simple-task", OnEvents: []string{"user:create"}},		func(ctx v0Worker.HatchetContext, input SimpleInput) (*SimpleResult, error) {			return &SimpleResult{TransformedMessage: strings.ToLower(input.Message)}, nil		},		hatchet,	)	_, err = hatchet.Worker(worker.WorkerOpts{		Name:      "worker",		Workflows: []workflow.WorkflowBase{simple},	})	if err != nil {		log.Fatal(err)	}}

V1 Reflection SDK (Current):

package mainimport (	"log"	"strings"	hatchet "github.com/hatchet-dev/hatchet/sdks/go")type SimpleInput struct {	Message string `json:"message"`}type SimpleResult struct {	TransformedMessage string `json:"result"`}func V1() {	client, err := hatchet.NewClient()	if err != nil {		log.Fatal(err)	}	workflow := client.NewStandaloneTask("simple-workflow", func(ctx hatchet.Context, input SimpleInput) (SimpleResult, error) {		log.Println("executed step1")		return SimpleResult{TransformedMessage: strings.ToLower(input.Message)}, nil	}, hatchet.WithWorkflowEvents("user:create"))	_, err = client.NewWorker(		"worker",		hatchet.WithWorkflows(workflow),	)	if err != nil {		log.Fatal(err)	}}

Migration Checklist

From V0 to V1 Reflection SDK

  • Update import: github.com/hatchet-dev/hatchet/pkg/clientgithub.com/hatchet-dev/hatchet/sdks/go
  • Change client creation: client.New()hatchet.NewClient()
  • Convert WorkflowJob to NewWorkflow() with tasks
  • Replace RegisterWorkflow() with WithWorkflows() option
  • Update function signatures to use typed inputs/outputs
  • Replace worker.HatchetContext with hatchet.Context

From V1 Generics to V1 Reflection SDK

  • Update import: github.com/hatchet-dev/hatchet/pkg/v1github.com/hatchet-dev/hatchet/sdks/go
  • Change client creation: v1.NewHatchetClient()hatchet.NewClient()
  • Remove factory imports and usage
  • Convert factory.NewTask() to NewStandaloneTask() or workflow tasks
  • Remove explicit type parameters (generics)
  • Update function return types (remove pointers where appropriate)
  • Replace create.StandaloneTask{} structs with option functions

Common Patterns

Error Handling and Retries

task := workflow.NewTask("resilient-task", func(ctx hatchet.Context, input any) (any, error) {
    // Your task logic here
    return result, nil
},
    hatchet.WithRetries(5),
    hatchet.WithRetryBackoff(2.0, time.Second*30), // 2x backoff, max 30s
)

Child Workflows

parentTask := workflow.NewTask("parent", func(ctx hatchet.Context, input any) (any, error) {
    // Spawn child workflow
    result, err := childWorkflow.Run(ctx, input, hatchet.WithRunKey("key"))
    if err != nil {
        return nil, err
    }

    return result, nil
})

Bulk Operations

// Run multiple instances of a workflow
runInputs := []hatchet.RunManyOpt{
    {Input: map[string]string{"user": "alice"}},
    {Input: map[string]string{"user": "bob"}},
    {Input: map[string]string{"user": "charlie"}},
}

renRefs, err := client.RunMany(ctx, "bulk-workflow", runInputs)

This guide should cover all major migration scenarios between the three Go SDK versions. The V1 Reflection SDK provides the most ergonomic API while maintaining full compatibility with the Hatchet platform.

Last updated on August 25, 2026

On this page