Repository: Tochemey/goakt
Pull request #460 (2024-09-07 13:51:00)

refactor: clean the addressing engine
1. Cleanup the actor addressing engine
2. Rename `GossipPort` to `DiscoveryPort` in `discovery.Node` (**breaking changes**)
3. Rename `ClusterConfig` method `WithGossipPort` to `WithDiscoveryPort` (**breaking changes**)
4. Rename `ClusterConfig` method `GossipPort()` to `DiscoveryPort()` (**breaking changes**)
5. Rename kubernetes config `GossipPortName` to `DiscoveryPortName` (**breaking changes**)

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/Tochemey/goakt/pull/460?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) Report
Attention: Patch coverage is `94.44444%` with `15 lines` in your changes missing coverage. Please review.
> Project coverage is 86.47%. Comparing base [(`524330a`)](https://app.codecov.io/gh/Tochemey/goakt/commit/524330aec3d767412ca307c9216631b01bd792ea?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) to head [(`67a3457`)](https://app.codecov.io/gh/Tochemey/goakt/commit/67a34574f40271216ee19cdcc1b6173128a5144e?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene).
> Report is 1 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/Tochemey/goakt/pull/460?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) | Patch % | Lines |
|---|---|---|
| [actors/pid.go](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&filepath=actors%2Fpid.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene#diff-YWN0b3JzL3BpZC5nbw==) | 90.47% | [5 Missing and 1 partial :warning: ](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) |
| [actors/redistribution.go](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&filepath=actors%2Fredistribution.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene#diff-YWN0b3JzL3JlZGlzdHJpYnV0aW9uLmdv) | 53.84% | [2 Missing and 4 partials :warning: ](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) |
| [address/address.go](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&filepath=address%2Faddress.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene#diff-YWRkcmVzcy9hZGRyZXNzLmdv) | 97.64% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) |
| [actors/actor\_system.go](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&filepath=actors%2Factor_system.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene#diff-YWN0b3JzL2FjdG9yX3N5c3RlbS5nbw==) | 98.38% | [0 Missing and 1 partial :warning: ](https://app.codecov.io/gh/Tochemey/goakt/pull/460?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main     #460      +/-   ##
==========================================
- Coverage   86.62%   86.47%   -0.15%     
==========================================
  Files          47       46       -1     
  Lines        3581     3571      -10     
==========================================
- Hits         3102     3088      -14     
- Misses        339      341       +2     
- Partials      140      142       +2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/Tochemey/goakt/pull/460?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Arsene).


Patch:
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
new file mode 100644
index 0000000..64819e4
--- /dev/null
+++ b/.github/workflows/stale.yml
@@ -0,0 +1,36 @@
+name: Stale
+
+on:
+  workflow_dispatch:
+  schedule:
+    - cron: '0 12 * * *'
+
+jobs:
+  Stale:
+    runs-on: ubuntu-latest
+    name: Run stale
+    steps:
+      - name: Checkout
+        id: checkout
+        uses: actions/checkout@v4
+      - name: Stale
+        id: stale
+        uses: sonia-corporation/stale@2.5.0
+        with:
+          pull-request-stale-label: stale-label
+          pull-request-days-before-stale: 14
+          pull-request-days-before-close: 10
+          pull-request-ignore-all-assignees: true
+          pull-request-delete-branch-after-close: true
+          pull-request-stale-comment: |
+            This pull is inactive since 14 days!
+            If there is no activity, it will be closed in two weeks.
+          issue-stale-label: inactive
+          issue-ignore-all-assignees: true
+          issue-days-before-stale: 14
+          issue-days-before-close: 10
+          issue-stale-comment: |
+            This issue is inactive since 14 days!
+            If there is no activity, it will be closed in two weeks.
+          issue-add-labels-after-close: |
+            closed-due-to-inactivity
diff --git a/README.md b/README.md
index 58db7f3..14cd13c 100644
--- a/README.md
+++ b/README.md
@@ -447,7 +447,7 @@ const (
     namespace          = "default"
     applicationName    = "accounts"
     actorSystemName    = "AccountsSystem"
-    gossipPortName     = "gossip-port"
+    discoveryPortName  = "discovery-port"
     peersPortName      = "peers-port"
     remotingPortName   = "remoting-port"
 )
@@ -457,7 +457,7 @@ config := kubernetes.Config{
     ApplicationName:  applicationName,
     ActorSystemName:  actorSystemName,
     Namespace:        namespace,
-    GossipPortName:   gossipPortName,
+    DiscoveryPortName:   gossipPortName,
     RemotingPortName: remotingPortName,
     PeersPortName:  peersPortName,
 }
diff --git a/actors/actor_system.go b/actors/actor_system.go
index 5f300b2..1c31e0e 100644
--- a/actors/actor_system.go
+++ b/actors/actor_system.go
@@ -46,8 +46,8 @@ import (
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/types/known/anypb"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/discovery"
-	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/hash"
 	"github.com/tochemey/goakt/v2/internal/cluster"
 	"github.com/tochemey/goakt/v2/internal/eventstream"
@@ -95,12 +95,12 @@ type ActorSystem interface {
 	// RemoteActor returns the address of a remote actor when cluster is enabled
 	// When the cluster mode is not enabled an actor not found error will be returned
 	// One can always check whether cluster is enabled before calling this method or just use the ActorOf method.
-	RemoteActor(ctx context.Context, actorName string) (addr *goaktpb.Address, err error)
+	RemoteActor(ctx context.Context, actorName string) (addr *address.Address, err error)
 	// ActorOf returns an existing actor in the local system or in the cluster when clustering is enabled
 	// When cluster mode is activated, the PID will be nil.
 	// When remoting is enabled this method will return and error
 	// An actor not found error is return when the actor is not found.
-	ActorOf(ctx context.Context, actorName string) (addr *goaktpb.Address, pid *PID, err error)
+	ActorOf(ctx context.Context, actorName string) (addr *address.Address, pid *PID, err error)
 	// InCluster states whether the actor system is running within a cluster of nodes
 	InCluster() bool
 	// GetPartition returns the partition where a given actor is located
@@ -117,11 +117,11 @@ type ActorSystem interface {
 	// This requires remoting to be enabled on the actor system.
 	// This will send the given message to the actor after the given interval specified
 	// The message will be sent once
-	RemoteScheduleOnce(ctx context.Context, message proto.Message, address *goaktpb.Address, interval time.Duration) error
+	RemoteScheduleOnce(ctx context.Context, message proto.Message, address *address.Address, interval time.Duration) error
 	// ScheduleWithCron schedules a message to be sent to an actor in the future using a cron expression.
 	ScheduleWithCron(ctx context.Context, message proto.Message, pid *PID, cronExpression string) error
 	// RemoteScheduleWithCron schedules a message to be sent to an actor in the future using a cron expression.
-	RemoteScheduleWithCron(ctx context.Context, message proto.Message, address *goaktpb.Address, cronExpression string) error
+	RemoteScheduleWithCron(ctx context.Context, message proto.Message, address *address.Address, cronExpression string) error
 	// PeerAddress returns the actor system address known in the cluster. That address is used by other nodes to communicate with the actor system.
 	// This address is empty when cluster mode is not activated
 	PeerAddress() string
@@ -181,9 +181,9 @@ type actorSystem struct {
 	// This allows to handle remote messaging
 	remotingEnabled atomic.Bool
 	// Specifies the remoting port
-	remotingPort int32
+	port int32
 	// Specifies the remoting host
-	remotingHost string
+	host string
 	// Specifies the remoting server
 	remotingServer *stdhttp.Server
 
@@ -191,7 +191,7 @@ type actorSystem struct {
 	clusterEnabled atomic.Bool
 	// cluster mode
 	cluster            cluster.Interface
-	actorsChan         chan *internalpb.WireActor
+	actorsChan         chan *internalpb.ActorRef
 	clusterEventsChan  <-chan *cluster.Event
 	clusterSyncStopSig chan types.Unit
 	partitionHasher    hash.Hasher
@@ -240,7 +240,7 @@ func NewActorSystem(name string, opts ...Option) (ActorSystem, error) {
 
 	system := &actorSystem{
 		actors:                 newPIDMap(1_000),
-		actorsChan:             make(chan *internalpb.WireActor, 10),
+		actorsChan:             make(chan *internalpb.ActorRef, 10),
 		name:                   name,
 		logger:                 log.New(log.ErrorLevel, os.Stderr),
 		expireActorAfter:       DefaultPassivationTimeout,
@@ -262,8 +262,8 @@ func NewActorSystem(name string, opts ...Option) (ActorSystem, error) {
 		peersCacheMu:           &sync.RWMutex{},
 		peersCache:             make(map[string][]byte),
 		peersStateLoopInterval: DefaultPeerStateLoopInterval,
-		remotingPort:           -1,
-		remotingHost:           "",
+		port:                   0,
+		host:                   "127.0.0.1",
 	}
 
 	system.started.Store(false)
@@ -341,7 +341,7 @@ func (x *actorSystem) ScheduleOnce(ctx context.Context, message proto.Message, p
 // This requires remoting to be enabled on the actor system.
 // This will send the given message to the actor after the given interval specified
 // The message will be sent once
-func (x *actorSystem) RemoteScheduleOnce(ctx context.Context, message proto.Message, address *goaktpb.Address, interval time.Duration) error {
+func (x *actorSystem) RemoteScheduleOnce(ctx context.Context, message proto.Message, address *address.Address, interval time.Duration) error {
 	return x.scheduler.RemoteScheduleOnce(ctx, message, address, interval)
 }
 
@@ -351,7 +351,7 @@ func (x *actorSystem) ScheduleWithCron(ctx context.Context, message proto.Messag
 }
 
 // RemoteScheduleWithCron schedules a message to be sent to an actor in the future using a cron expression.
-func (x *actorSystem) RemoteScheduleWithCron(ctx context.Context, message proto.Message, address *goaktpb.Address, cronExpression string) error {
+func (x *actorSystem) RemoteScheduleWithCron(ctx context.Context, message proto.Message, address *address.Address, cronExpression string) error {
 	return x.scheduler.RemoteScheduleWithCron(ctx, message, address, cronExpression)
 }
 
@@ -401,7 +401,7 @@ func (x *actorSystem) Spawn(ctx context.Context, name string, actor Actor) (*PID
 	}
 
 	// set the default actor path assuming we are running locally
-	actorPath := x.actorPath(name)
+	actorPath := x.actorAddress(name)
 	pid, exist := x.actors.get(actorPath)
 	if exist {
 		if pid.IsRunning() {
@@ -458,7 +458,7 @@ func (x *actorSystem) Kill(ctx context.Context, name string) error {
 		return ErrActorSystemNotStarted
 	}
 
-	actorPath := x.actorPath(name)
+	actorPath := x.actorAddress(name)
 	pid, exist := x.actors.get(actorPath)
 	if exist {
 		// stop the given actor. No need to record error in the span context
@@ -475,7 +475,7 @@ func (x *actorSystem) ReSpawn(ctx context.Context, name string) (*PID, error) {
 		return nil, ErrActorSystemNotStarted
 	}
 
-	actorPath := x.actorPath(name)
+	actorPath := x.actorAddress(name)
 	pid, exist := x.actors.get(actorPath)
 	if exist {
 		if err := pid.Restart(ctx); err != nil {
@@ -526,7 +526,7 @@ func (x *actorSystem) PeerAddress() string {
 // When cluster mode is activated, the PID will be nil.
 // When remoting is enabled this method will return and error
 // An actor not found error is return when the actor is not found.
-func (x *actorSystem) ActorOf(ctx context.Context, actorName string) (addr *goaktpb.Address, pid *PID, err error) {
+func (x *actorSystem) ActorOf(ctx context.Context, actorName string) (addr *address.Address, pid *PID, err error) {
 	x.locker.Lock()
 
 	if !x.started.Load() {
@@ -535,10 +535,10 @@ func (x *actorSystem) ActorOf(ctx context.Context, actorName string) (addr *goak
 	}
 
 	// first check whether the actor exist locally
-	actorPath := x.actorPath(actorName)
+	actorPath := x.actorAddress(actorName)
 	if lpid, ok := x.actors.get(actorPath); ok {
 		x.locker.Unlock()
-		return lpid.ActorPath().RemoteAddress(), lpid, nil
+		return lpid.Address(), lpid, nil
 	}
 
 	// check in the cluster
@@ -556,7 +556,7 @@ func (x *actorSystem) ActorOf(ctx context.Context, actorName string) (addr *goak
 		}
 
 		x.locker.Unlock()
-		return actor.GetActorAddress(), nil, nil
+		return address.From(actor.GetActorAddress()), nil, nil
 	}
 
 	if x.remotingEnabled.Load() {
@@ -579,7 +579,7 @@ func (x *actorSystem) LocalActor(actorName string) (*PID, error) {
 		return nil, ErrActorSystemNotStarted
 	}
 
-	actorPath := x.actorPath(actorName)
+	actorPath := x.actorAddress(actorName)
 	if lpid, ok := x.actors.get(actorPath); ok {
 		x.locker.Unlock()
 		return lpid, nil
@@ -593,7 +593,7 @@ func (x *actorSystem) LocalActor(actorName string) (*PID, error) {
 // RemoteActor returns the address of a remote actor when cluster is enabled
 // When the cluster mode is not enabled an actor not found error will be returned
 // One can always check whether cluster is enabled before calling this method or just use the ActorOf method.
-func (x *actorSystem) RemoteActor(ctx context.Context, actorName string) (addr *goaktpb.Address, err error) {
+func (x *actorSystem) RemoteActor(ctx context.Context, actorName string) (addr *address.Address, err error) {
 	x.locker.Lock()
 
 	if !x.started.Load() {
@@ -620,7 +620,7 @@ func (x *actorSystem) RemoteActor(ctx context.Context, actorName string) (addr *
 	}
 
 	x.locker.Unlock()
-	return actor.GetActorAddress(), nil
+	return address.From(actor.GetActorAddress()), nil
 }
 
 // Start starts the actor system
@@ -701,10 +701,10 @@ func (x *actorSystem) Stop(ctx context.Context) error {
 		return err
 	}
 	// remove the supervisor from the actors list
-	x.actors.delete(x.supervisor.ActorPath())
+	x.actors.delete(x.supervisor.Address())
 
 	for _, actor := range x.Actors() {
-		x.actors.delete(actor.ActorPath())
+		x.actors.delete(actor.Address())
 		if err := actor.Shutdown(ctx); err != nil {
 			x.reset()
 			return err
@@ -725,7 +725,7 @@ func (x *actorSystem) RemoteLookup(ctx context.Context, request *connect.Request
 		return nil, connect.NewError(connect.CodeFailedPrecondition, ErrRemotingDisabled)
 	}
 
-	remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+	remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 	if remoteAddr != net.JoinHostPort(msg.GetHost(), strconv.Itoa(int(msg.GetPort()))) {
 		return nil, connect.NewError(connect.CodeInvalidArgument, ErrInvalidHost)
 	}
@@ -744,14 +744,14 @@ func (x *actorSystem) RemoteLookup(ctx context.Context, request *connect.Request
 		return connect.NewResponse(&internalpb.RemoteLookupResponse{Address: actor.GetActorAddress()}), nil
 	}
 
-	actorPath := NewPath(msg.GetName(), NewAddress(x.Name(), msg.GetHost(), int(msg.GetPort())))
-	pid, exist := x.actors.get(actorPath)
+	addr := address.New(msg.GetName(), x.Name(), msg.GetHost(), int(msg.GetPort()))
+	pid, exist := x.actors.get(addr)
 	if !exist {
-		logger.Error(ErrAddressNotFound(actorPath.String()).Error())
-		return nil, ErrAddressNotFound(actorPath.String())
+		logger.Error(ErrAddressNotFound(addr.String()).Error())
+		return nil, ErrAddressNotFound(addr.String())
 	}
 
-	return connect.NewResponse(&internalpb.RemoteLookupResponse{Address: pid.ActorPath().RemoteAddress()}), nil
+	return connect.NewResponse(&internalpb.RemoteLookupResponse{Address: pid.Address().Address}), nil
 }
 
 // RemoteAsk is used to send a message to an actor remotely and expect a response
@@ -786,16 +786,16 @@ func (x *actorSystem) RemoteAsk(ctx context.Context, stream *connect.BidiStream[
 		receiver := message.GetReceiver()
 		name := receiver.GetName()
 
-		remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+		remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 		if remoteAddr != net.JoinHostPort(receiver.GetHost(), strconv.Itoa(int(receiver.GetPort()))) {
 			return connect.NewError(connect.CodeInvalidArgument, ErrInvalidHost)
 		}
 
-		actorPath := NewPath(name, NewAddress(x.name, x.remotingHost, int(x.remotingPort)))
-		pid, exist := x.actors.get(actorPath)
+		addr := x.actorAddress(name)
+		pid, exist := x.actors.get(addr)
 		if !exist {
-			logger.Error(ErrAddressNotFound(actorPath.String()).Error())
-			return ErrAddressNotFound(actorPath.String())
+			logger.Error(ErrAddressNotFound(addr.String()).Error())
+			return ErrAddressNotFound(addr.String())
 		}
 
 		timeout := x.askTimeout
@@ -851,17 +851,11 @@ func (x *actorSystem) RemoteTell(ctx context.Context, stream *connect.ClientStre
 	eg.Go(func() error {
 		for request := range requestc {
 			receiver := request.GetRemoteMessage().GetReceiver()
-			actorPath := NewPath(
-				receiver.GetName(),
-				NewAddress(
-					x.Name(),
-					receiver.GetHost(),
-					int(receiver.GetPort())))
-
-			pid, exist := x.actors.get(actorPath)
+			addr := address.New(receiver.GetName(), x.Name(), receiver.GetHost(), int(receiver.GetPort()))
+			pid, exist := x.actors.get(addr)
 			if !exist {
-				logger.Error(ErrAddressNotFound(actorPath.String()).Error())
-				return ErrAddressNotFound(actorPath.String())
+				logger.Error(ErrAddressNotFound(addr.String()).Error())
+				return ErrAddressNotFound(addr.String())
 			}
 
 			if err := x.handleRemoteTell(ctx, pid, request.GetRemoteMessage()); err != nil {
@@ -889,12 +883,12 @@ func (x *actorSystem) RemoteReSpawn(ctx context.Context, request *connect.Reques
 		return nil, connect.NewError(connect.CodeFailedPrecondition, ErrRemotingDisabled)
 	}
 
-	remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+	remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 	if remoteAddr != net.JoinHostPort(msg.GetHost(), strconv.Itoa(int(msg.GetPort()))) {
 		return nil, connect.NewError(connect.CodeInvalidArgument, ErrInvalidHost)
 	}
 
-	actorPath := NewPath(msg.GetName(), NewAddress(x.Name(), msg.GetHost(), int(msg.GetPort())))
+	actorPath := address.New(msg.GetName(), x.Name(), msg.GetHost(), int(msg.GetPort()))
 	pid, exist := x.actors.get(actorPath)
 	if !exist {
 		logger.Error(ErrAddressNotFound(actorPath.String()).Error())
@@ -919,12 +913,12 @@ func (x *actorSystem) RemoteStop(ctx context.Context, request *connect.Request[i
 		return nil, connect.NewError(connect.CodeFailedPrecondition, ErrRemotingDisabled)
 	}
 
-	remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+	remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 	if remoteAddr != net.JoinHostPort(msg.GetHost(), strconv.Itoa(int(msg.GetPort()))) {
 		return nil, connect.NewError(connect.CodeInvalidArgument, ErrInvalidHost)
 	}
 
-	actorPath := NewPath(msg.GetName(), NewAddress(x.Name(), msg.GetHost(), int(msg.GetPort())))
+	actorPath := address.New(msg.GetName(), x.Name(), msg.GetHost(), int(msg.GetPort()))
 	pid, exist := x.actors.get(actorPath)
 	if !exist {
 		logger.Error(ErrAddressNotFound(actorPath.String()).Error())
@@ -948,7 +942,7 @@ func (x *actorSystem) RemoteSpawn(ctx context.Context, request *connect.Request[
 		return nil, connect.NewError(connect.CodeFailedPrecondition, ErrRemotingDisabled)
 	}
 
-	remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+	remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 	if remoteAddr != net.JoinHostPort(msg.GetHost(), strconv.Itoa(int(msg.GetPort()))) {
 		return nil, connect.NewError(connect.CodeInvalidArgument, ErrInvalidHost)
 	}
@@ -982,7 +976,7 @@ func (x *actorSystem) GetNodeMetric(_ context.Context, request *connect.Request[
 
 	req := request.Msg
 
-	remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+	remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 	if remoteAddr != req.GetNodeAddress() {
 		return nil, connect.NewError(connect.CodeInvalidArgument, ErrInvalidHost)
 	}
@@ -1001,7 +995,7 @@ func (x *actorSystem) GetKinds(_ context.Context, request *connect.Request[inter
 	}
 
 	req := request.Msg
-	remoteAddr := fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort)
+	remoteAddr := fmt.Sprintf("%s:%d", x.host, x.port)
 
 	// routine check
 	if remoteAddr != req.GetNodeAddress() {
@@ -1039,10 +1033,8 @@ func (x *actorSystem) getSupervisor() *PID {
 func (x *actorSystem) setActor(actor *PID) {
 	x.actors.set(actor)
 	if x.clusterEnabled.Load() {
-		x.actorsChan <- &internalpb.WireActor{
-			ActorName:    actor.Name(),
-			ActorAddress: actor.ActorPath().RemoteAddress(),
-			ActorPath:    actor.ActorPath().String(),
+		x.actorsChan <- &internalpb.ActorRef{
+			ActorAddress: actor.Address().Address,
 			ActorType:    types.TypeName(actor.Actor()),
 		}
 	}
@@ -1059,11 +1051,11 @@ func (x *actorSystem) enableClustering(ctx context.Context) error {
 	}
 
 	node := &discovery.Node{
-		Name:         x.Name(),
-		Host:         x.remotingHost,
-		GossipPort:   x.clusterConfig.GossipPort(),
-		PeersPort:    x.clusterConfig.PeersPort(),
-		RemotingPort: int(x.remotingPort),
+		Name:          x.Name(),
+		Host:          x.host,
+		DiscoveryPort: x.clusterConfig.DiscoveryPort(),
+		PeersPort:     x.clusterConfig.PeersPort(),
+		RemotingPort:  int(x.port),
 	}
 
 	clusterEngine, err := cluster.NewEngine(
@@ -1123,7 +1115,7 @@ func (x *actorSystem) enableRemoting(ctx context.Context) {
 	var err error
 	if x.metricEnabled.Load() {
 		interceptor, err = otelconnect.NewInterceptor(
-			otelconnect.WithMeterProvider(x.telemetry.MeterProvider),
+			otelconnect.WithMeterProvider(x.telemetry.MeterProvider()),
 		)
 		if err != nil {
 			x.logger.Panic(fmt.Errorf("failed to initialize observability feature: %w", err))
@@ -1135,13 +1127,13 @@ func (x *actorSystem) enableRemoting(ctx context.Context) {
 		opts = append(opts, connect.WithInterceptors(interceptor))
 	}
 
-	remotingHost, remotingPort, err := tcp.GetHostPort(fmt.Sprintf("%s:%d", x.remotingHost, x.remotingPort))
+	remotingHost, remotingPort, err := tcp.GetHostPort(fmt.Sprintf("%s:%d", x.host, x.port))
 	if err != nil {
 		x.logger.Panic(fmt.Errorf("failed to resolve remoting TCP address: %w", err))
 	}
 
-	x.remotingHost = remotingHost
-	x.remotingPort = int32(remotingPort)
+	x.host = remotingHost
+	x.port = int32(remotingPort)
 
 	remotingServicePath, remotingServiceHandler := internalpbconnect.NewRemotingServiceHandler(x, opts...)
 	clusterServicePath, clusterServiceHandler := internalpbconnect.NewClusterServiceHandler(x, opts...)
@@ -1149,7 +1141,7 @@ func (x *actorSystem) enableRemoting(ctx context.Context) {
 	mux := stdhttp.NewServeMux()
 	mux.Handle(remotingServicePath, remotingServiceHandler)
 	mux.Handle(clusterServicePath, clusterServiceHandler)
-	server := http.NewServer(ctx, x.remotingHost, remotingPort, mux)
+	server := http.NewServer(ctx, x.host, remotingPort, mux)
 
 	go func() {
 		if err := server.ListenAndServe(); err != nil {
@@ -1186,10 +1178,10 @@ func (x *actorSystem) janitor() {
 			case <-ticker.C:
 				for _, actor := range x.Actors() {
 					if !actor.IsRunning() {
-						x.logger.Infof("removing actor=%s from system", actor.ActorPath().Name())
-						x.actors.delete(actor.ActorPath())
+						x.logger.Infof("removing actor=%s from system", actor.Address().Name())
+						x.actors.delete(actor.Address())
 						if x.InCluster() {
-							if err := x.cluster.RemoveActor(context.Background(), actor.ActorPath().Name()); err != nil {
+							if err := x.cluster.RemoveActor(context.Background(), actor.Address().Name()); err != nil {
 								x.logger.Error(err.Error())
 								// TODO: stop or continue
 							}
@@ -1210,7 +1202,7 @@ func (x *actorSystem) janitor() {
 
 // registerMetrics register the PID metrics with OTel instrumentation.
 func (x *actorSystem) registerMetrics() error {
-	meter := x.telemetry.Meter
+	meter := x.telemetry.Meter()
 	metrics, err := metric.NewActorSystemMetric(meter)
 	if err != nil {
 		return err
@@ -1229,7 +1221,7 @@ func (x *actorSystem) replicationLoop() {
 	for actor := range x.actorsChan {
 		// never replicate system actors because there are specific to the
 		// running node
-		if isSystemName(actor.GetActorName()) {
+		if isSystemName(actor.GetActorAddress().GetName()) {
 			continue
 		}
 		if x.InCluster() {
@@ -1367,9 +1359,9 @@ func (x *actorSystem) processPeerState(ctx context.Context, peer *cluster.Peer)
 // configPID constructs a PID provided the actor name and the actor kind
 // this is a utility function used when spawning actors
 func (x *actorSystem) configPID(ctx context.Context, name string, actor Actor) (*PID, error) {
-	actorPath := NewPath(name, NewAddress(x.name, "", -1))
-	if x.remotingEnabled.Load() {
-		actorPath = NewPath(name, NewAddress(x.name, x.remotingHost, int(x.remotingPort)))
+	addr := x.actorAddress(name)
+	if err := addr.Validate(); err != nil {
+		return nil, err
 	}
 
 	// define the pid options
@@ -1402,7 +1394,7 @@ func (x *actorSystem) configPID(ctx context.Context, name string, actor Actor) (
 	}
 
 	pid, err := newPID(ctx,
-		actorPath,
+		addr,
 		actor,
 		pidOpts...)
 
@@ -1418,8 +1410,8 @@ func (x *actorSystem) getSystemActorName(nameType nameType) string {
 		return fmt.Sprintf("%s%s%s-%d-%d",
 			systemNames[nameType],
 			strings.ToTitle(x.name),
-			x.remotingHost,
-			x.remotingPort,
+			x.host,
+			x.port,
 			time.Now().UnixNano())
 	}
 	return fmt.Sprintf("%s%s-%d",
@@ -1432,7 +1424,7 @@ func isSystemName(name string) bool {
 	return strings.HasPrefix(name, systemNamePrefix)
 }
 
-// actorPath returns the actor path provided the actor name
-func (x *actorSystem) actorPath(name string) *Path {
-	return NewPath(name, NewAddress(x.name, x.remotingHost, int(x.remotingPort)))
+// actorAddress returns the actor path provided the actor name
+func (x *actorSystem) actorAddress(name string) *address.Address {
+	return address.New(name, x.name, x.host, int(x.port))
 }
diff --git a/actors/address.go b/actors/address.go
deleted file mode 100644
index 75649bb..0000000
--- a/actors/address.go
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2022-2024 Tochemey
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package actors
-
-import (
-	"bytes"
-	"strconv"
-)
-
-// Address represents the physical location under which an Actor can be
-// reached. Examples are local addresses, identified by the ActorSystem’s name,
-// and remote addresses, identified by protocol, host and port.
-type Address struct {
-	// host is the host address
-	host string
-	// port is the port number
-	port int
-	// system is the actor system name
-	system string
-	// protocol is the protocol
-	protocol string
-}
-
-// NewAddress creates an instance of Address
-func NewAddress(system string, host string, port int) *Address {
-	return &Address{
-		host:     host,
-		port:     port,
-		system:   system,
-		protocol: protocol,
-	}
-}
-
-// WithHost sets the hosts of a given Address and returns a new instance of the address
-func (a *Address) WithHost(host string) (*Address, error) {
-	if a.IsLocal() {
-		return nil, ErrLocalAddress
-	}
-	return NewAddress(a.System(), host, a.Port()), nil
-}
-
-// WithPort sets the port of a given Address and returns a new instance of the address
-func (a *Address) WithPort(port int) (*Address, error) {
-	if a.IsLocal() {
-		return nil, ErrLocalAddress
-	}
-	return NewAddress(a.System(), a.Host(), port), nil
-}
-
-// WithSystem sets the actor system of a given Address and returns a new instance of the address
-func (a *Address) WithSystem(system string) *Address {
-	return NewAddress(system, a.Host(), a.Port())
-}
-
-// Host returns the host
-func (a *Address) Host() string {
-	return a.host
-}
-
-// Port returns the port number
-func (a *Address) Port() int {
-	return a.port
-}
-
-// System returns the actor system name
-func (a *Address) System() string {
-	return a.system
-}
-
-// Protocol returns the protocol
-func (a *Address) Protocol() string {
-	return a.protocol
-}
-
-// HostPort returns the host and port in the following string format
-// @host:port
-func (a *Address) HostPort() string {
-	// create a bytes buffer instance
-	buf := bytes.NewBuffer(nil)
-	// write the host and port value when it is remote
-	if a.IsRemote() {
-		buf.WriteString(a.host)
-		buf.WriteByte(':')
-		buf.WriteString(strconv.Itoa(a.port))
-	}
-
-	// return the constructed string
-	return buf.String()
-}
-
-// String returns the canonical String representation of this Address formatted as:
-// `protocol://system@host:port`
-func (a *Address) String() string {
-	buf := bytes.NewBuffer(nil)
-	buf.WriteString(a.protocol)
-	buf.WriteString("://")
-	buf.WriteString(a.system)
-	buf.WriteByte('@')
-
-	// write the host and port to the bytes buffer when it is remote
-	if a.IsRemote() {
-		buf.WriteString(a.host)
-		buf.WriteByte(':')
-		buf.WriteString(strconv.Itoa(a.port))
-	}
-
-	// returns the constructed string value
-	return buf.String()
-}
-
-// IsLocal helps set the actor address locally
-func (a *Address) IsLocal() bool {
-	return len(a.host) == 0
-}
-
-// IsRemote states whether the actor address is in the remote environment
-// This happens when remoting is enabled
-func (a *Address) IsRemote() bool {
-	return len(a.host) > 0 && a.port > 0
-}
diff --git a/actors/api.go b/actors/api.go
index b900132..0eabf82 100644
--- a/actors/api.go
+++ b/actors/api.go
@@ -34,7 +34,7 @@ import (
 	"google.golang.org/protobuf/types/known/anypb"
 	"google.golang.org/protobuf/types/known/durationpb"
 
-	"github.com/tochemey/goakt/v2/goaktpb"
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/internal/http"
 	"github.com/tochemey/goakt/v2/internal/internalpb"
 	"github.com/tochemey/goakt/v2/internal/internalpb/internalpbconnect"
@@ -113,7 +113,7 @@ func BatchAsk(ctx context.Context, to *PID, timeout time.Duration, messages ...p
 }
 
 // RemoteTell sends a message to an actor remotely without expecting any reply
-func RemoteTell(ctx context.Context, to *goaktpb.Address, message proto.Message) error {
+func RemoteTell(ctx context.Context, to *address.Address, message proto.Message) error {
 	marshaled, err := anypb.New(message)
 	if err != nil {
 		return ErrInvalidRemoteMessage(err)
@@ -126,8 +126,8 @@ func RemoteTell(ctx context.Context, to *goaktpb.Address, message proto.Message)
 
 	request := &internalpb.RemoteTellRequest{
 		RemoteMessage: &internalpb.RemoteMessage{
-			Sender:   RemoteNoSender,
-			Receiver: to,
+			Sender:   address.NoSender,
+			Receiver: to.Address,
 			Message:  marshaled,
 		},
 	}
@@ -152,7 +152,7 @@ func RemoteTell(ctx context.Context, to *goaktpb.Address, message proto.Message)
 }
 
 // RemoteAsk sends a synchronous message to another actor remotely and expect a response.
-func RemoteAsk(ctx context.Context, to *goaktpb.Address, message proto.Message, timeout time.Duration) (response *anypb.Any, err error) {
+func RemoteAsk(ctx context.Context, to *address.Address, message proto.Message, timeout time.Duration) (response *anypb.Any, err error) {
 	marshaled, err := anypb.New(message)
 	if err != nil {
 		return nil, ErrInvalidRemoteMessage(err)
@@ -165,8 +165,8 @@ func RemoteAsk(ctx context.Context, to *goaktpb.Address, message proto.Message,
 
 	request := &internalpb.RemoteAskRequest{
 		RemoteMessage: &internalpb.RemoteMessage{
-			Sender:   RemoteNoSender,
-			Receiver: to,
+			Sender:   address.NoSender,
+			Receiver: to.Address,
 			Message:  marshaled,
 		},
 		Timeout: durationpb.New(timeout),
@@ -209,7 +209,7 @@ func RemoteAsk(ctx context.Context, to *goaktpb.Address, message proto.Message,
 }
 
 // RemoteLookup look for an actor address on a remote node.
-func RemoteLookup(ctx context.Context, host string, port int, name string) (addr *goaktpb.Address, err error) {
+func RemoteLookup(ctx context.Context, host string, port int, name string) (addr *address.Address, err error) {
 	remoteClient := internalpbconnect.NewRemotingServiceClient(
 		http.NewClient(),
 		http.URL(host, port),
@@ -230,11 +230,11 @@ func RemoteLookup(ctx context.Context, host string, port int, name string) (addr
 		return nil, err
 	}
 
-	return response.Msg.GetAddress(), nil
+	return address.From(response.Msg.GetAddress()), nil
 }
 
 // RemoteBatchTell sends bulk asynchronous messages to an actor
-func RemoteBatchTell(ctx context.Context, to *goaktpb.Address, messages ...proto.Message) error {
+func RemoteBatchTell(ctx context.Context, to *address.Address, messages ...proto.Message) error {
 	var requests []*internalpb.RemoteTellRequest
 	for _, message := range messages {
 		packed, err := anypb.New(message)
@@ -244,8 +244,8 @@ func RemoteBatchTell(ctx context.Context, to *goaktpb.Address, messages ...proto
 
 		requests = append(requests, &internalpb.RemoteTellRequest{
 			RemoteMessage: &internalpb.RemoteMessage{
-				Sender:   RemoteNoSender,
-				Receiver: to,
+				Sender:   address.NoSender,
+				Receiver: to.Address,
 				Message:  packed,
 			},
 		})
@@ -280,7 +280,7 @@ func RemoteBatchTell(ctx context.Context, to *goaktpb.Address, messages ...proto
 }
 
 // RemoteBatchAsk sends bulk messages to an actor with responses expected
-func RemoteBatchAsk(ctx context.Context, to *goaktpb.Address, messages ...proto.Message) (responses []*anypb.Any, err error) {
+func RemoteBatchAsk(ctx context.Context, to *address.Address, messages ...proto.Message) (responses []*anypb.Any, err error) {
 	var requests []*internalpb.RemoteAskRequest
 	for _, message := range messages {
 		packed, err := anypb.New(message)
@@ -290,8 +290,8 @@ func RemoteBatchAsk(ctx context.Context, to *goaktpb.Address, messages ...proto.
 
 		requests = append(requests, &internalpb.RemoteAskRequest{
 			RemoteMessage: &internalpb.RemoteMessage{
-				Sender:   RemoteNoSender,
-				Receiver: to,
+				Sender:   address.NoSender,
+				Receiver: to.Address,
 				Message:  packed,
 			},
 		})
@@ -426,8 +426,8 @@ func toReceiveContext(ctx context.Context, to *PID, message proto.Message) (*Rec
 		if err != nil {
 			return nil, ErrInvalidRemoteMessage(err)
 		}
-		return newReceiveContext(ctx, NoSender, to, actual).withRemoteSender(msg.GetSender()), nil
+		return newReceiveContext(ctx, NoSender, to, actual).withRemoteSender(address.From(msg.GetSender())), nil
 	default:
-		return newReceiveContext(ctx, NoSender, to, message).withRemoteSender(RemoteNoSender), nil
+		return newReceiveContext(ctx, NoSender, to, message).withRemoteSender(address.From(address.NoSender)), nil
 	}
 }
diff --git a/actors/cluster_config.go b/actors/cluster_config.go
index fe1d9fa..165c00e 100644
--- a/actors/cluster_config.go
+++ b/actors/cluster_config.go
@@ -40,7 +40,7 @@ type ClusterConfig struct {
 	partitionCount     uint64
 	minimumPeersQuorum uint32
 	replicaCount       uint32
-	gossipPort         int
+	discoveryPort      int
 	peersPort          int
 	kinds              []Actor
 }
@@ -81,9 +81,9 @@ func (x *ClusterConfig) WithKinds(kinds ...Actor) *ClusterConfig {
 	return x
 }
 
-// WithGossipPort sets the gossip port
-func (x *ClusterConfig) WithGossipPort(port int) *ClusterConfig {
-	x.gossipPort = port
+// WithDiscoveryPort sets the discovery port
+func (x *ClusterConfig) WithDiscoveryPort(port int) *ClusterConfig {
+	x.discoveryPort = port
 	return x
 }
 
@@ -119,9 +119,9 @@ func (x *ClusterConfig) MinimumPeersQuorum() uint32 {
 	return x.minimumPeersQuorum
 }
 
-// GossipPort returns the gossip port
-func (x *ClusterConfig) GossipPort() int {
-	return x.gossipPort
+// DiscoveryPort returns the discovery port
+func (x *ClusterConfig) DiscoveryPort() int {
+	return x.discoveryPort
 }
 
 // PeersPort returns the peers port
@@ -141,7 +141,7 @@ func (x *ClusterConfig) Validate() error {
 		AddAssertion(x.discovery != nil, "discovery provider is not set").
 		AddAssertion(x.partitionCount > 0, "partition count need to greater than zero").
 		AddAssertion(x.minimumPeersQuorum >= 1, "minimum peers quorum must be at least one").
-		AddAssertion(x.gossipPort > 0, "gossip port is invalid").
+		AddAssertion(x.discoveryPort > 0, "gossip port is invalid").
 		AddAssertion(x.peersPort > 0, "peers port is invalid").
 		AddAssertion(len(x.kinds) > 1, "actor kinds are not defined").
 		AddAssertion(x.replicaCount > 0, "actor replicaCount is invalid").
diff --git a/actors/option.go b/actors/option.go
index 6780eda..f8d7074 100644
--- a/actors/option.go
+++ b/actors/option.go
@@ -104,14 +104,14 @@ func WithTelemetry(telemetry *telemetry.Telemetry) Option {
 func WithRemoting(host string, port int32) Option {
 	return OptionFunc(func(a *actorSystem) {
 		a.remotingEnabled.Store(true)
-		a.remotingPort = port
-		a.remotingHost = host
+		a.port = port
+		a.host = host
 	})
 }
 
 // WithClustering enables the cluster mode.
 // Deprecated: use rather WithCluster which offers a fluent api to set cluster configuration
-func WithClustering(provider discovery.Provider, partitionCount uint64, minimumPeersQuorum uint16, gossipPort, peersPort int, kinds ...Actor) Option {
+func WithClustering(provider discovery.Provider, partitionCount uint64, minimumPeersQuorum uint16, discoveryPort, peersPort int, kinds ...Actor) Option {
 	return OptionFunc(func(a *actorSystem) {
 		a.clusterEnabled.Store(true)
 		replicaCount := 2
@@ -122,7 +122,7 @@ func WithClustering(provider discovery.Provider, partitionCount uint64, minimumP
 		a.clusterConfig = NewClusterConfig().
 			WithDiscovery(provider).
 			WithPartitionCount(partitionCount).
-			WithGossipPort(gossipPort).
+			WithDiscoveryPort(discoveryPort).
 			WithPeersPort(peersPort).
 			WithMinimumPeersQuorum(uint32(minimumPeersQuorum)).
 			WithReplicaCount(uint32(replicaCount)).
diff --git a/actors/path.go b/actors/path.go
deleted file mode 100644
index e84d288..0000000
--- a/actors/path.go
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * MIT License
- *
- * Copyright (c) 2022-2024 Tochemey
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-package actors
-
-import (
-	"fmt"
-	"strings"
-
-	"github.com/google/uuid"
-	"github.com/pkg/errors"
-
-	"github.com/tochemey/goakt/v2/goaktpb"
-	"github.com/tochemey/goakt/v2/internal/validation"
-)
-
-// Path is a unique path to an actor
-type Path struct {
-	// specifies the Address under which this path can be reached
-	address *Address
-	// specifies the name of the actor that this path refers to.
-	name string
-	// specifies the internal unique id of the actor that this path refer to.
-	id uuid.UUID
-	// specifies the path for the parent actor.
-	parent *Path
-}
-
-var _ validation.Validator = (*Path)(nil)
-
-// NewPath creates an immutable Path
-func NewPath(name string, address *Address) *Path {
-	// create the instance and return it
-	return &Path{
-		address: address,
-		name:    name,
-		id:      uuid.New(),
-	}
-}
-
-// Parent returns the parent path
-func (p *Path) Parent() *Path {
-	return p.parent
-}
-
-// WithParent sets the parent actor path and returns a new path
-// This function is immutable
-func (p *Path) WithParent(parent *Path) *Path {
-	newPath := NewPath(p.name, p.address)
-	newPath.parent = parent
-	return newPath
-}
-
-// Address returns the address of the path
-func (p *Path) Address() *Address {
-	return p.address
-}
-
-// Name returns the name of the actor that this path refers to.
-func (p *Path) Name() string {
-	return p.name
-}
-
-// ID returns the internal unique id of the actor that this path refer to.
-func (p *Path) ID() uuid.UUID {
-	return p.id
-}
-
-// String returns the string representation of an actorPath
-func (p *Path) String() string {
-	return fmt.Sprintf("%s/%s", p.address.String(), p.name)
-}
-
-// Equals is used to compare two paths
-func (p *Path) Equals(x *Path) bool {
-	return p.ID().ID() == x.ID().ID() && p.String() == x.String()
-}
-
-// RemoteAddress returns the remote from path
-func (p *Path) RemoteAddress() *goaktpb.Address {
-	// only returns a remote address when we are in a remote scope otherwise return nil
-	if !p.address.IsRemote() {
-		return nil
-	}
-	return &goaktpb.Address{
-		Host: p.address.Host(),
-		Port: int32(p.address.Port()),
-		Name: p.Name(),
-		Id:   p.ID().String(),
-	}
-}
-
-// Validate returns an error when the path is not valid
-func (p *Path) Validate() error {
-	pattern := "^[a-zA-Z0-9][a-zA-Z0-9-_\\.]*$"
-	customErr := errors.New("path name must contain only word characters (i.e. [a-zA-Z0-9] plus non-leading '-' or '_')")
-	return validation.
-		New(validation.FailFast()).
-		AddValidator(validation.NewPatternValidator(pattern, strings.TrimSpace(p.name), customErr)).
-		AddAssertion(p.address != nil, "address is required").
-		Validate()
-}
diff --git a/actors/pid.go b/actors/pid.go
index 06421b2..a0cd167 100644
--- a/actors/pid.go
+++ b/actors/pid.go
@@ -43,6 +43,7 @@ import (
 	"google.golang.org/protobuf/types/known/anypb"
 	"google.golang.org/protobuf/types/known/timestamppb"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/future"
 	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/internal/errorschain"
@@ -78,8 +79,8 @@ type PID struct {
 	// specifies the message processor
 	actor Actor
 
-	// specifies the actor path
-	actorPath *Path
+	// specifies the actor address
+	address *address.Address
 
 	// helps determine whether the actor should handle public or not.
 	running atomic.Bool
@@ -168,14 +169,14 @@ type PID struct {
 }
 
 // newPID creates a new pid
-func newPID(ctx context.Context, actorPath *Path, actor Actor, opts ...pidOption) (*PID, error) {
-	// actor path is required
-	if actorPath == nil {
-		return nil, errors.New("actorPath is required")
+func newPID(ctx context.Context, address *address.Address, actor Actor, opts ...pidOption) (*PID, error) {
+	// actor address is required
+	if address == nil {
+		return nil, errors.New("address is required")
 	}
 
-	// validate actor path
-	if err := actorPath.Validate(); err != nil {
+	// validate the address
+	if err := address.Validate(); err != nil {
 		return nil, err
 	}
 
@@ -189,7 +190,7 @@ func newPID(ctx context.Context, actorPath *Path, actor Actor, opts ...pidOption
 		watchersList:                   slice.New[*watcher](),
 		watchedList:                    newPIDMap(10),
 		telemetry:                      telemetry.New(),
-		actorPath:                      actorPath,
+		address:                        address,
 		fieldsLocker:                   new(sync.RWMutex),
 		stopLocker:                     new(sync.Mutex),
 		httpClient:                     http.NewClient(),
@@ -235,7 +236,7 @@ func newPID(ctx context.Context, actorPath *Path, actor Actor, opts ...pidOption
 	}
 
 	if p.metricEnabled.Load() {
-		metrics, err := metric.NewActorMetric(p.telemetry.Meter)
+		metrics, err := metric.NewActorMetric(p.telemetry.Meter())
 		if err != nil {
 			return nil, err
 		}
@@ -254,12 +255,12 @@ func newPID(ctx context.Context, actorPath *Path, actor Actor, opts ...pidOption
 // ID is a convenient method that returns the actor unique identifier
 // An actor unique identifier is its address in the actor system.
 func (pid *PID) ID() string {
-	return pid.ActorPath().String()
+	return pid.Address().String()
 }
 
 // Name returns the actor given name
 func (pid *PID) Name() string {
-	return pid.ActorPath().Name()
+	return pid.Address().Name()
 }
 
 // Equals is a convenient method to compare two PIDs
@@ -277,12 +278,13 @@ func (pid *PID) Child(name string) (*PID, error) {
 	if !pid.IsRunning() {
 		return nil, ErrDead
 	}
-	childActorPath := NewPath(name, pid.ActorPath().Address()).WithParent(pid.ActorPath())
-	if cid, ok := pid.children.get(childActorPath); ok {
+
+	childAddress := address.New(name, pid.Address().System(), pid.Address().Host(), pid.Address().Port()).WithParent(pid.Address())
+	if cid, ok := pid.children.get(childAddress); ok {
 		pid.childrenCount.Inc()
 		return cid, nil
 	}
-	return nil, ErrActorNotFound(childActorPath.String())
+	return nil, ErrActorNotFound(childAddress.String())
 }
 
 // Parents returns the list of all direct parents of a given actor.
@@ -338,7 +340,7 @@ func (pid *PID) Stop(ctx context.Context, cid *PID) error {
 	children := pid.children
 	pid.fieldsLocker.RUnlock()
 
-	if cid, ok := children.get(cid.ActorPath()); ok {
+	if cid, ok := children.get(cid.Address()); ok {
 		if err := cid.Shutdown(ctx); err != nil {
 			return err
 		}
@@ -346,7 +348,7 @@ func (pid *PID) Stop(ctx context.Context, cid *PID) error {
 		return nil
 	}
 
-	return ErrActorNotFound(cid.ActorPath().String())
+	return ErrActorNotFound(cid.Address().String())
 }
 
 // IsRunning returns true when the actor is alive ready to process messages and false
@@ -363,10 +365,10 @@ func (pid *PID) ActorSystem() ActorSystem {
 	return sys
 }
 
-// ActorPath returns the path of the actor
-func (pid *PID) ActorPath() *Path {
+// Address returns address of the actor
+func (pid *PID) Address() *address.Address {
 	pid.fieldsLocker.RLock()
-	path := pid.actorPath
+	path := pid.address
 	pid.fieldsLocker.RUnlock()
 	return path
 }
@@ -374,11 +376,11 @@ func (pid *PID) ActorPath() *Path {
 // Restart restarts the actor.
 // During restart all messages that are in the mailbox and not yet processed will be ignored
 func (pid *PID) Restart(ctx context.Context) error {
-	if pid == nil || pid.ActorPath() == nil {
+	if pid == nil || pid.Address() == nil {
 		return ErrUndefinedActor
 	}
 
-	pid.logger.Debugf("restarting actor=(%s)", pid.actorPath.String())
+	pid.logger.Debugf("restarting actor=(%s)", pid.address.String())
 
 	if pid.IsRunning() {
 		if err := pid.Shutdown(ctx); err != nil {
@@ -412,7 +414,7 @@ func (pid *PID) Restart(ctx context.Context) error {
 
 	if pid.eventsStream != nil {
 		pid.eventsStream.Publish(eventsTopic, &goaktpb.ActorRestarted{
-			Address:     pid.ActorPath().RemoteAddress(),
+			Address:     pid.Address().Address,
 			RestartedAt: timestamppb.Now(),
 		})
 	}
@@ -427,13 +429,12 @@ func (pid *PID) SpawnChild(ctx context.Context, name string, actor Actor) (*PID,
 		return nil, ErrDead
 	}
 
-	childActorPath := NewPath(name, pid.ActorPath().Address()).WithParent(pid.ActorPath())
-
+	childAddress := address.New(name, pid.Address().System(), pid.Address().Host(), pid.Address().Port()).WithParent(pid.Address())
 	pid.fieldsLocker.RLock()
 	children := pid.children
 	pid.fieldsLocker.RUnlock()
 
-	if cid, ok := children.get(childActorPath); ok {
+	if cid, ok := children.get(childAddress); ok {
 		return cid, nil
 	}
 
@@ -457,7 +458,7 @@ func (pid *PID) SpawnChild(ctx context.Context, name string, actor Actor) (*PID,
 	}
 
 	cid, err := newPID(ctx,
-		childActorPath,
+		childAddress,
 		actor,
 		opts...,
 	)
@@ -476,9 +477,9 @@ func (pid *PID) SpawnChild(ctx context.Context, name string, actor Actor) (*PID,
 
 	if eventsStream != nil {
 		eventsStream.Publish(eventsTopic, &goaktpb.ActorChildCreated{
-			Address:   cid.ActorPath().RemoteAddress(),
+			Address:   cid.Address().Address,
 			CreatedAt: timestamppb.Now(),
-			Parent:    pid.ActorPath().RemoteAddress(),
+			Parent:    pid.Address().Address,
 		})
 	}
 
@@ -628,11 +629,7 @@ func (pid *PID) BatchAsk(ctx context.Context, to *PID, messages ...proto.Message
 
 // RemoteLookup look for an actor address on a remote node.
 func (pid *PID) RemoteLookup(ctx context.Context, host string, port int, name string) (addr *goaktpb.Address, err error) {
-	remoteClient, err := pid.remotingClient(host, port)
-	if err != nil {
-		return nil, err
-	}
-
+	remoteClient := pid.remotingClient(host, port)
 	request := connect.NewRequest(&internalpb.RemoteLookupRequest{
 		Host: host,
 		Port: int32(port),
@@ -652,28 +649,25 @@ func (pid *PID) RemoteLookup(ctx context.Context, host string, port int, name st
 }
 
 // RemoteTell sends a message to an actor remotely without expecting any reply
-func (pid *PID) RemoteTell(ctx context.Context, to *goaktpb.Address, message proto.Message) error {
+func (pid *PID) RemoteTell(ctx context.Context, to *address.Address, message proto.Message) error {
 	marshaled, err := anypb.New(message)
 	if err != nil {
 		return err
 	}
 
-	remoteService, err := pid.remotingClient(to.GetHost(), int(to.GetPort()))
-	if err != nil {
-		return err
-	}
+	remoteService := pid.remotingClient(to.GetHost(), int(to.GetPort()))
 
 	sender := &goaktpb.Address{
-		Host: pid.ActorPath().Address().Host(),
-		Port: int32(pid.ActorPath().Address().Port()),
-		Name: pid.ActorPath().Name(),
-		Id:   pid.ActorPath().ID().String(),
+		Host: pid.Address().Host(),
+		Port: int32(pid.Address().Port()),
+		Name: pid.Address().Name(),
+		Id:   pid.Address().ID(),
 	}
 
 	request := &internalpb.RemoteTellRequest{
 		RemoteMessage: &internalpb.RemoteMessage{
 			Sender:   sender,
-			Receiver: to,
+			Receiver: to.Address,
 			Message:  marshaled,
 		},
 	}
@@ -703,31 +697,26 @@ func (pid *PID) RemoteTell(ctx context.Context, to *goaktpb.Address, message pro
 }
 
 // RemoteAsk sends a synchronous message to another actor remotely and expect a response.
-func (pid *PID) RemoteAsk(ctx context.Context, to *goaktpb.Address, message proto.Message) (response *anypb.Any, err error) {
+func (pid *PID) RemoteAsk(ctx context.Context, to *address.Address, message proto.Message) (response *anypb.Any, err error) {
 	marshaled, err := anypb.New(message)
 	if err != nil {
 		return nil, err
 	}
 
-	remoteService, err := pid.remotingClient(to.GetHost(), int(to.GetPort()))
-	if err != nil {
-		return nil, err
-	}
-
-	senderPath := pid.ActorPath()
-	senderAddress := senderPath.Address()
+	remoteService := pid.remotingClient(to.GetHost(), int(to.GetPort()))
 
+	senderAddress := pid.Address()
 	sender := &goaktpb.Address{
 		Host: senderAddress.Host(),
 		Port: int32(senderAddress.Port()),
-		Name: senderPath.Name(),
-		Id:   senderPath.ID().String(),
+		Name: senderAddress.Name(),
+		Id:   senderAddress.ID(),
 	}
 
 	request := &internalpb.RemoteAskRequest{
 		RemoteMessage: &internalpb.RemoteMessage{
 			Sender:   sender,
-			Receiver: to,
+			Receiver: to.Address,
 			Message:  marshaled,
 		},
 	}
@@ -771,19 +760,16 @@ func (pid *PID) RemoteAsk(ctx context.Context, to *goaktpb.Address, message prot
 
 // RemoteBatchTell sends a batch of messages to a remote actor in a way fire-and-forget manner
 // Messages are processed one after the other in the order they are sent.
-func (pid *PID) RemoteBatchTell(ctx context.Context, to *goaktpb.Address, messages ...proto.Message) error {
+func (pid *PID) RemoteBatchTell(ctx context.Context, to *address.Address, messages ...proto.Message) error {
 	if len(messages) == 1 {
 		return pid.RemoteTell(ctx, to, messages[0])
 	}
 
-	senderPath := pid.ActorPath()
-	senderAddress := senderPath.Address()
-
 	sender := &goaktpb.Address{
-		Host: senderAddress.Host(),
-		Port: int32(senderAddress.Port()),
-		Name: senderPath.Name(),
-		Id:   senderPath.ID().String(),
+		Host: pid.Address().Host(),
+		Port: int32(pid.Address().Port()),
+		Name: pid.Address().Name(),
+		Id:   pid.Address().ID(),
 	}
 
 	var requests []*internalpb.RemoteTellRequest
@@ -796,16 +782,13 @@ func (pid *PID) RemoteBatchTell(ctx context.Context, to *goaktpb.Address, messag
 		requests = append(requests, &internalpb.RemoteTellRequest{
 			RemoteMessage: &internalpb.RemoteMessage{
 				Sender:   sender,
-				Receiver: to,
+				Receiver: to.Address,
 				Message:  packed,
 			},
 		})
 	}
 
-	remoteService, err := pid.remotingClient(to.GetHost(), int(to.GetPort()))
-	if err != nil {
-		return err
-	}
+	remoteService := pid.remotingClient(to.GetHost(), int(to.GetPort()))
 
 	stream := remoteService.RemoteTell(ctx)
 	for _, request := range requests {
@@ -831,15 +814,12 @@ func (pid *PID) RemoteBatchTell(ctx context.Context, to *goaktpb.Address, messag
 // RemoteBatchAsk sends a synchronous bunch of messages to a remote actor and expect responses in the same order as the messages.
 // Messages are processed one after the other in the order they are sent.
 // This can hinder performance if it is not properly used.
-func (pid *PID) RemoteBatchAsk(ctx context.Context, to *goaktpb.Address, messages ...proto.Message) (responses []*anypb.Any, err error) {
-	senderPath := pid.ActorPath()
-	senderAddress := senderPath.Address()
-
+func (pid *PID) RemoteBatchAsk(ctx context.Context, to *address.Address, messages ...proto.Message) (responses []*anypb.Any, err error) {
 	sender := &goaktpb.Address{
-		Host: senderAddress.Host(),
-		Port: int32(senderAddress.Port()),
-		Name: senderPath.Name(),
-		Id:   senderPath.ID().String(),
+		Host: pid.Address().Host(),
+		Port: int32(pid.Address().Port()),
+		Name: pid.Address().Name(),
+		Id:   pid.Address().ID(),
 	}
 
 	var requests []*internalpb.RemoteAskRequest
@@ -852,17 +832,13 @@ func (pid *PID) RemoteBatchAsk(ctx context.Context, to *goaktpb.Address, message
 		requests = append(requests, &internalpb.RemoteAskRequest{
 			RemoteMessage: &internalpb.RemoteMessage{
 				Sender:   sender,
-				Receiver: to,
+				Receiver: to.Address,
 				Message:  packed,
 			},
 		})
 	}
 
-	remoteService, err := pid.remotingClient(to.GetHost(), int(to.GetPort()))
-	if err != nil {
-		return nil, err
-	}
-
+	remoteService := pid.remotingClient(to.GetHost(), int(to.GetPort()))
 	stream := remoteService.RemoteAsk(ctx)
 	errc := make(chan error, 1)
 
@@ -904,42 +880,31 @@ func (pid *PID) RemoteBatchAsk(ctx context.Context, to *goaktpb.Address, message
 
 // RemoteStop stops an actor on a remote node
 func (pid *PID) RemoteStop(ctx context.Context, host string, port int, name string) error {
-	remoteService, err := pid.remotingClient(host, port)
-	if err != nil {
-		return err
-	}
-
+	remoteService := pid.remotingClient(host, port)
 	request := connect.NewRequest(&internalpb.RemoteStopRequest{
 		Host: host,
 		Port: int32(port),
 		Name: name,
 	})
-
-	if _, err = remoteService.RemoteStop(ctx, request); err != nil {
+	if _, err := remoteService.RemoteStop(ctx, request); err != nil {
 		code := connect.CodeOf(err)
 		if code == connect.CodeNotFound {
 			return nil
 		}
 		return err
 	}
-
 	return nil
 }
 
 // RemoteSpawn creates an actor on a remote node. The given actor needs to be registered on the remote node using the Register method of ActorSystem
 func (pid *PID) RemoteSpawn(ctx context.Context, host string, port int, name, actorType string) error {
-	remoteService, err := pid.remotingClient(host, port)
-	if err != nil {
-		return err
-	}
-
+	remoteService := pid.remotingClient(host, port)
 	request := connect.NewRequest(&internalpb.RemoteSpawnRequest{
 		Host:      host,
 		Port:      int32(port),
 		ActorName: name,
 		ActorType: actorType,
 	})
-
 	if _, err := remoteService.RemoteSpawn(ctx, request); err != nil {
 		code := connect.CodeOf(err)
 		if code == connect.CodeFailedPrecondition {
@@ -952,31 +917,24 @@ func (pid *PID) RemoteSpawn(ctx context.Context, host string, port int, name, ac
 		}
 		return err
 	}
-
 	return nil
 }
 
 // RemoteReSpawn restarts an actor on a remote node.
 func (pid *PID) RemoteReSpawn(ctx context.Context, host string, port int, name string) error {
-	remoteService, err := pid.remotingClient(host, port)
-	if err != nil {
-		return err
-	}
-
+	remoteService := pid.remotingClient(host, port)
 	request := connect.NewRequest(&internalpb.RemoteReSpawnRequest{
 		Host: host,
 		Port: int32(port),
 		Name: name,
 	})
-
-	if _, err = remoteService.RemoteReSpawn(ctx, request); err != nil {
+	if _, err := remoteService.RemoteReSpawn(ctx, request); err != nil {
 		code := connect.CodeOf(err)
 		if code == connect.CodeNotFound {
 			return nil
 		}
 		return err
 	}
-
 	return nil
 }
 
@@ -990,7 +948,7 @@ func (pid *PID) Shutdown(ctx context.Context) error {
 	pid.logger.Info("Shutdown process has started...")
 
 	if !pid.running.Load() {
-		pid.logger.Infof("Actor=%s is offline. Maybe it has been passivated or stopped already", pid.ActorPath().String())
+		pid.logger.Infof("Actor=%s is offline. Maybe it has been passivated or stopped already", pid.Address().String())
 		return nil
 	}
 
@@ -1006,7 +964,7 @@ func (pid *PID) Shutdown(ctx context.Context) error {
 
 	if pid.eventsStream != nil {
 		pid.eventsStream.Publish(eventsTopic, &goaktpb.ActorStopped{
-			Address:   pid.ActorPath().RemoteAddress(),
+			Address:   pid.Address().Address,
 			StoppedAt: timestamppb.Now(),
 		})
 	}
@@ -1033,7 +991,7 @@ func (pid *PID) UnWatch(cid *PID) {
 		w := item.Value
 		if w.WatcherID.Equals(cid) {
 			w.Done <- types.Unit{}
-			pid.watchees().delete(cid.ActorPath())
+			pid.watchees().delete(cid.Address())
 			cid.watchers().Delete(item.Index)
 			break
 		}
@@ -1089,7 +1047,7 @@ func (pid *PID) init(ctx context.Context) error {
 
 	if pid.eventsStream != nil {
 		pid.eventsStream.Publish(eventsTopic, &goaktpb.ActorStarted{
-			Address:   pid.ActorPath().RemoteAddress(),
+			Address:   pid.Address().Address,
 			StartedAt: timestamppb.Now(),
 		})
 	}
@@ -1162,7 +1120,7 @@ func (pid *PID) freeChildren(ctx context.Context) error {
 	for _, child := range pid.Children() {
 		pid.logger.Debugf("parent=(%s) disowning child=(%s)", pid.ID(), child.ID())
 		pid.UnWatch(child)
-		pid.children.delete(child.ActorPath())
+		pid.children.delete(child.Address())
 		if err := child.Shutdown(ctx); err != nil {
 			errwrap := fmt.Errorf(
 				"parent=(%s) failed to disown child=(%s): %w", pid.ID(), child.ID(),
@@ -1242,28 +1200,28 @@ func (pid *PID) passivationLoop() {
 	ticker.Stop()
 
 	if !pid.IsRunning() {
-		pid.logger.Infof("Actor=%s is offline. No need to passivate", pid.ActorPath().String())
+		pid.logger.Infof("Actor=%s is offline. No need to passivate", pid.Address().String())
 		return
 	}
 
-	pid.logger.Infof("Passivation mode has been triggered for actor=%s...", pid.ActorPath().String())
+	pid.logger.Infof("Passivation mode has been triggered for actor=%s...", pid.Address().String())
 
 	ctx := context.Background()
 	if err := pid.doStop(ctx); err != nil {
 		// TODO: rethink properly about PostStop error handling
-		pid.logger.Errorf("failed to passivate actor=(%s): reason=(%v)", pid.ActorPath().String(), err)
+		pid.logger.Errorf("failed to passivate actor=(%s): reason=(%v)", pid.Address().String(), err)
 		return
 	}
 
 	if pid.eventsStream != nil {
 		event := &goaktpb.ActorPassivated{
-			Address:      pid.ActorPath().RemoteAddress(),
+			Address:      pid.Address().Address,
 			PassivatedAt: timestamppb.Now(),
 		}
 		pid.eventsStream.Publish(eventsTopic, event)
 	}
 
-	pid.logger.Infof("Actor=%s successfully passivated", pid.ActorPath().String())
+	pid.logger.Infof("Actor=%s successfully passivated", pid.Address().String())
 }
 
 // setBehavior is a utility function that helps set the actor behavior
@@ -1303,7 +1261,7 @@ func (pid *PID) doStop(ctx context.Context) error {
 	// TODO: just signal stash processing done and ignore the messages or process them
 	if pid.stashBuffer != nil {
 		if err := pid.unstashAll(); err != nil {
-			pid.logger.Errorf("actor=(%s) failed to unstash messages", pid.ActorPath().String())
+			pid.logger.Errorf("actor=(%s) failed to unstash messages", pid.Address().String())
 			return err
 		}
 	}
@@ -1345,7 +1303,7 @@ func (pid *PID) doStop(ctx context.Context) error {
 		return err
 	}
 
-	pid.logger.Infof("Shutdown process is on going for actor=%s...", pid.ActorPath().String())
+	pid.logger.Infof("Shutdown process is on going for actor=%s...", pid.Address().String())
 	pid.reset()
 	return pid.actor.PostStop(ctx)
 }
@@ -1360,7 +1318,7 @@ func (pid *PID) removeChild(cid *PID) {
 		return
 	}
 
-	path := cid.ActorPath()
+	path := cid.Address()
 	if c, ok := pid.children.get(path); ok {
 		if c.IsRunning() {
 			return
@@ -1403,12 +1361,12 @@ func (pid *PID) toDeadletterQueue(receiveCtx *ReceiveContext, err error) {
 	msg, _ := anypb.New(receiveCtx.Message())
 	var senderAddr *goaktpb.Address
 	if receiveCtx.Sender() != nil || receiveCtx.Sender() != NoSender {
-		senderAddr = receiveCtx.Sender().ActorPath().RemoteAddress()
+		senderAddr = receiveCtx.Sender().Address().Address
 	}
 
 	pid.eventsStream.Publish(eventsTopic, &goaktpb.Deadletter{
 		Sender:   senderAddr,
-		Receiver: pid.actorPath.RemoteAddress(),
+		Receiver: pid.Address().Address,
 		Message:  msg,
 		SendTime: timestamppb.Now(),
 		Reason:   err.Error(),
@@ -1417,7 +1375,7 @@ func (pid *PID) toDeadletterQueue(receiveCtx *ReceiveContext, err error) {
 
 // registerMetrics register the PID metrics with OTel instrumentation.
 func (pid *PID) registerMetrics() error {
-	meter := pid.telemetry.Meter
+	meter := pid.telemetry.Meter()
 	metrics := pid.metrics
 	_, err := meter.RegisterCallback(func(_ context.Context, observer otelmetric.Observer) error {
 		observer.ObserveInt64(metrics.ChildrenCount(), pid.childrenCount.Load())
@@ -1434,37 +1392,30 @@ func (pid *PID) registerMetrics() error {
 }
 
 // clientOptions returns the gRPC client connections options
-func (pid *PID) clientOptions() ([]connect.ClientOption, error) {
+func (pid *PID) clientOptions() []connect.ClientOption {
 	var interceptor *otelconnect.Interceptor
-	var err error
 	if pid.metricEnabled.Load() {
-		interceptor, err = otelconnect.NewInterceptor(
-			otelconnect.WithTracerProvider(pid.telemetry.TracerProvider),
-			otelconnect.WithMeterProvider(pid.telemetry.MeterProvider))
-		if err != nil {
-			return nil, fmt.Errorf("failed to initialize observability feature: %w", err)
-		}
+		// no need to handle the error because a NoOp trace and meter provider will be
+		// returned by the telemetry engine when none is provided
+		interceptor, _ = otelconnect.NewInterceptor(
+			otelconnect.WithTracerProvider(pid.telemetry.TraceProvider()),
+			otelconnect.WithMeterProvider(pid.telemetry.MeterProvider()))
 	}
 
 	var clientOptions []connect.ClientOption
 	if interceptor != nil {
 		clientOptions = append(clientOptions, connect.WithInterceptors(interceptor))
 	}
-	return clientOptions, err
+	return clientOptions
 }
 
 // remotingClient returns an instance of the Remote Service client
-func (pid *PID) remotingClient(host string, port int) (internalpbconnect.RemotingServiceClient, error) {
-	clientOptions, err := pid.clientOptions()
-	if err != nil {
-		return nil, err
-	}
-
+func (pid *PID) remotingClient(host string, port int) internalpbconnect.RemotingServiceClient {
 	return internalpbconnect.NewRemotingServiceClient(
 		pid.httpClient,
 		http.URL(host, port),
-		clientOptions...,
-	), nil
+		pid.clientOptions()...,
+	)
 }
 
 // handleCompletion processes a long-running task and pipe the result to
@@ -1501,7 +1452,7 @@ func (pid *PID) handleCompletion(ctx context.Context, completion *taskCompletion
 	// make sure that the receiver is still alive
 	to := completion.Receiver
 	if !to.IsRunning() {
-		pid.logger.Errorf("unable to pipe message to actor=(%s): not running", to.ActorPath().String())
+		pid.logger.Errorf("unable to pipe message to actor=(%s): not running", to.Address().String())
 		return
 	}
 
@@ -1535,7 +1486,7 @@ func (pid *PID) supervise(cid *PID, watcher *watcher) {
 // handleStopDirective handles the testSupervisor stop directive
 func (pid *PID) handleStopDirective(cid *PID) {
 	pid.UnWatch(cid)
-	pid.children.delete(cid.ActorPath())
+	pid.children.delete(cid.Address())
 	if err := cid.Shutdown(context.Background()); err != nil {
 		// this can enter into some infinite loop if we panic
 		// since we are just shutting down the actor we can just log the error
@@ -1560,7 +1511,7 @@ func (pid *PID) handleRestartDirective(cid *PID, maxRetries uint32, timeout time
 	if err != nil {
 		pid.logger.Error(err)
 		// remove the actor in case it is a child and stop it
-		pid.children.delete(cid.ActorPath())
+		pid.children.delete(cid.Address())
 		if err := cid.Shutdown(ctx); err != nil {
 			pid.logger.Error(err)
 		}
diff --git a/actors/pid_map.go b/actors/pid_map.go
index 55b76bf..aa7efaf 100644
--- a/actors/pid_map.go
+++ b/actors/pid_map.go
@@ -28,6 +28,8 @@ import (
 	"sync"
 
 	"go.uber.org/atomic"
+
+	"github.com/tochemey/goakt/v2/address"
 )
 
 type pidMap struct {
@@ -49,9 +51,9 @@ func (m *pidMap) len() int {
 }
 
 // get retrieves a pid by its address
-func (m *pidMap) get(path *Path) (pid *PID, ok bool) {
+func (m *pidMap) get(address *address.Address) (pid *PID, ok bool) {
 	m.mu.RLock()
-	pid, ok = m.mappings[path.String()]
+	pid, ok = m.mappings[address.String()]
 	m.mu.RUnlock()
 	return
 }
@@ -61,13 +63,13 @@ func (m *pidMap) set(pid *PID) {
 	m.mu.Lock()
 	defer m.mu.Unlock()
 	if pid != nil {
-		m.mappings[pid.ActorPath().String()] = pid
+		m.mappings[pid.Address().String()] = pid
 		m.size.Add(1)
 	}
 }
 
 // delete removes a pid from the map
-func (m *pidMap) delete(addr *Path) {
+func (m *pidMap) delete(addr *address.Address) {
 	m.mu.Lock()
 	delete(m.mappings, addr.String())
 	m.size.Add(-1)
diff --git a/actors/receive_context.go b/actors/receive_context.go
index ffd25b3..002cb2d 100644
--- a/actors/receive_context.go
+++ b/actors/receive_context.go
@@ -30,6 +30,7 @@ import (
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/types/known/anypb"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/future"
 	"github.com/tochemey/goakt/v2/goaktpb"
 )
@@ -39,7 +40,7 @@ type ReceiveContext struct {
 	ctx          context.Context
 	message      proto.Message
 	sender       *PID
-	remoteSender *goaktpb.Address
+	remoteSender *address.Address
 	response     chan proto.Message
 	self         *PID
 	err          error
@@ -58,7 +59,7 @@ func newReceiveContext(ctx context.Context, from, to *PID, message proto.Message
 }
 
 // withRemoteSender set the remote sender for a given context
-func (c *ReceiveContext) withRemoteSender(remoteSender *goaktpb.Address) *ReceiveContext {
+func (c *ReceiveContext) withRemoteSender(remoteSender *address.Address) *ReceiveContext {
 	c.remoteSender = remoteSender
 	return c
 }
@@ -90,8 +91,8 @@ func (c *ReceiveContext) Sender() *PID {
 }
 
 // RemoteSender defines the remote sender of the message if it is a remote message
-// This is set to RemoteNoSender when the message is not a remote message
-func (c *ReceiveContext) RemoteSender() *goaktpb.Address {
+// This is set to NoSender when the message is not a remote message
+func (c *ReceiveContext) RemoteSender() *address.Address {
 	return c.remoteSender
 }
 
@@ -220,7 +221,7 @@ func (c *ReceiveContext) BatchAsk(to *PID, messages ...proto.Message) (responses
 }
 
 // RemoteTell sends a message to an actor remotely without expecting any reply
-func (c *ReceiveContext) RemoteTell(to *goaktpb.Address, message proto.Message) {
+func (c *ReceiveContext) RemoteTell(to *address.Address, message proto.Message) {
 	recipient := c.self
 	ctx := context.WithoutCancel(c.ctx)
 	if err := recipient.RemoteTell(ctx, to, message); err != nil {
@@ -230,7 +231,7 @@ func (c *ReceiveContext) RemoteTell(to *goaktpb.Address, message proto.Message)
 
 // RemoteAsk is used to send a message to an actor remotely and expect a response
 // immediately.
-func (c *ReceiveContext) RemoteAsk(to *goaktpb.Address, message proto.Message) (response *anypb.Any) {
+func (c *ReceiveContext) RemoteAsk(to *address.Address, message proto.Message) (response *anypb.Any) {
 	recipient := c.self
 	ctx := context.WithoutCancel(c.ctx)
 	reply, err := recipient.RemoteAsk(ctx, to, message)
@@ -242,7 +243,7 @@ func (c *ReceiveContext) RemoteAsk(to *goaktpb.Address, message proto.Message) (
 
 // RemoteBatchTell sends a batch of messages to a remote actor in a way fire-and-forget manner
 // Messages are processed one after the other in the order they are sent.
-func (c *ReceiveContext) RemoteBatchTell(to *goaktpb.Address, messages ...proto.Message) {
+func (c *ReceiveContext) RemoteBatchTell(to *address.Address, messages ...proto.Message) {
 	recipient := c.self
 	ctx := context.WithoutCancel(c.ctx)
 	if err := recipient.RemoteBatchTell(ctx, to, messages...); err != nil {
@@ -253,7 +254,7 @@ func (c *ReceiveContext) RemoteBatchTell(to *goaktpb.Address, messages ...proto.
 // RemoteBatchAsk sends a synchronous bunch of messages to a remote actor and expect responses in the same order as the messages.
 // Messages are processed one after the other in the order they are sent.
 // This can hinder performance if it is not properly used.
-func (c *ReceiveContext) RemoteBatchAsk(to *goaktpb.Address, messages ...proto.Message) (responses []*anypb.Any) {
+func (c *ReceiveContext) RemoteBatchAsk(to *address.Address, messages ...proto.Message) (responses []*anypb.Any) {
 	recipient := c.self
 	ctx := context.WithoutCancel(c.ctx)
 	replies, err := recipient.RemoteBatchAsk(ctx, to, messages...)
diff --git a/actors/redistribution.go b/actors/redistribution.go
index 0354f60..f53706e 100644
--- a/actors/redistribution.go
+++ b/actors/redistribution.go
@@ -82,8 +82,8 @@ func (x *actorSystem) redistribute(ctx context.Context, event *cluster.Event) er
 	}
 
 	var (
-		leaderActors []*internalpb.WireActor
-		chunks       [][]*internalpb.WireActor
+		leaderActors []*internalpb.ActorRef
+		chunks       [][]*internalpb.ActorRef
 	)
 
 	x.logger.Debugf("total actors: %d on node left[%s]", actorsCount, nodeLeft.GetAddress())
@@ -94,7 +94,7 @@ func (x *actorSystem) redistribute(ctx context.Context, event *cluster.Event) er
 		quotient := actorsCount / totalPeers
 		remainder := actorsCount % totalPeers
 		leaderActors = peerState.GetActors()[:remainder]
-		chunks = slice.Chunk[*internalpb.WireActor](peerState.GetActors()[remainder:], quotient)
+		chunks = slice.Chunk[*internalpb.ActorRef](peerState.GetActors()[remainder:], quotient)
 	}
 
 	if len(chunks) > 0 {
@@ -106,23 +106,23 @@ func (x *actorSystem) redistribute(ctx context.Context, event *cluster.Event) er
 	eg.Go(func() error {
 		for _, actor := range leaderActors {
 			// never redistribute system actors
-			if isSystemName(actor.GetActorName()) {
+			if isSystemName(actor.GetActorAddress().GetName()) {
 				continue
 			}
 
-			x.logger.Debugf("re-creating actor=[(%s) of type (%s)]", actor.GetActorName(), actor.GetActorType())
+			x.logger.Debugf("re-creating actor=[(%s) of type (%s)]", actor.GetActorAddress().GetName(), actor.GetActorType())
 			iactor, err := x.reflection.ActorFrom(actor.GetActorType())
 			if err != nil {
-				x.logger.Errorf("failed to create actor=[(%s) of type (%s)]: %v", actor.GetActorName(), actor.GetActorType(), err)
+				x.logger.Errorf("failed to create actor=[(%s) of type (%s)]: %v", actor.GetActorAddress().GetName(), actor.GetActorType(), err)
 				return err
 			}
 
-			if _, err = x.Spawn(ctx, actor.GetActorName(), iactor); err != nil {
-				x.logger.Errorf("failed to spawn actor=[(%s) of type (%s)]: %v", actor.GetActorName(), actor.GetActorType(), err)
+			if _, err = x.Spawn(ctx, actor.GetActorAddress().GetName(), iactor); err != nil {
+				x.logger.Errorf("failed to spawn actor=[(%s) of type (%s)]: %v", actor.GetActorAddress().GetName(), actor.GetActorType(), err)
 				return err
 			}
 
-			x.logger.Debugf("actor=[(%s) of type (%s)] successfully re-created", actor.GetActorName(), actor.GetActorType())
+			x.logger.Debugf("actor=[(%s) of type (%s)] successfully re-created", actor.GetActorAddress().GetName(), actor.GetActorType())
 		}
 		return nil
 	})
@@ -146,16 +146,16 @@ func (x *actorSystem) redistribute(ctx context.Context, event *cluster.Event) er
 
 			for _, actor := range actors {
 				// never redistribute system actors
-				if isSystemName(actor.GetActorName()) {
+				if isSystemName(actor.GetActorAddress().GetName()) {
 					continue
 				}
 
-				x.logger.Debugf("re-creating actor=[(%s) of type (%s)]", actor.GetActorName(), actor.GetActorType())
-				if err := RemoteSpawn(ctx, state.GetHost(), int(state.GetRemotingPort()), actor.GetActorName(), actor.GetActorType()); err != nil {
+				x.logger.Debugf("re-creating actor=[(%s) of type (%s)]", actor.GetActorAddress().GetName(), actor.GetActorType())
+				if err := RemoteSpawn(ctx, state.GetHost(), int(state.GetRemotingPort()), actor.GetActorAddress().GetName(), actor.GetActorType()); err != nil {
 					x.logger.Error(err)
 					return err
 				}
-				x.logger.Debugf("actor=[(%s) of type (%s)] successfully re-created", actor.GetActorName(), actor.GetActorType())
+				x.logger.Debugf("actor=[(%s) of type (%s)] successfully re-created", actor.GetActorAddress().GetName(), actor.GetActorType())
 			}
 		}
 		return nil
diff --git a/actors/scheduler.go b/actors/scheduler.go
index e8f76a1..b51cb92 100644
--- a/actors/scheduler.go
+++ b/actors/scheduler.go
@@ -39,7 +39,7 @@ import (
 	"go.uber.org/atomic"
 	"google.golang.org/protobuf/proto"
 
-	"github.com/tochemey/goakt/v2/goaktpb"
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/internal/cluster"
 	"github.com/tochemey/goakt/v2/log"
 )
@@ -140,7 +140,7 @@ func (x *scheduler) ScheduleOnce(ctx context.Context, message proto.Message, pid
 		return true, nil
 	})
 
-	jobDetails := quartz.NewJobDetail(job, quartz.NewJobKey(pid.ActorPath().String()))
+	jobDetails := quartz.NewJobDetail(job, quartz.NewJobKey(pid.Address().String()))
 	if err := x.distributeJobKeyOrNot(ctx, jobDetails); err != nil {
 		if errors.Is(err, errSkipJobScheduling) {
 			return nil
@@ -155,7 +155,7 @@ func (x *scheduler) ScheduleOnce(ctx context.Context, message proto.Message, pid
 // This requires remoting to be enabled on the actor system.
 // This will send the given message to the actor after the given interval specified
 // The message will be sent once
-func (x *scheduler) RemoteScheduleOnce(ctx context.Context, message proto.Message, address *goaktpb.Address, interval time.Duration) error {
+func (x *scheduler) RemoteScheduleOnce(ctx context.Context, message proto.Message, address *address.Address, interval time.Duration) error {
 	x.mu.Lock()
 	defer x.mu.Unlock()
 
@@ -197,7 +197,7 @@ func (x *scheduler) ScheduleWithCron(ctx context.Context, message proto.Message,
 		return true, nil
 	})
 
-	jobDetails := quartz.NewJobDetail(job, quartz.NewJobKey(pid.ActorPath().String()))
+	jobDetails := quartz.NewJobDetail(job, quartz.NewJobKey(pid.Address().String()))
 	if err := x.distributeJobKeyOrNot(ctx, jobDetails); err != nil {
 		if errors.Is(err, errSkipJobScheduling) {
 			return nil
@@ -216,7 +216,7 @@ func (x *scheduler) ScheduleWithCron(ctx context.Context, message proto.Message,
 }
 
 // RemoteScheduleWithCron schedules a message to be sent to an actor in the future using a cron expression.
-func (x *scheduler) RemoteScheduleWithCron(ctx context.Context, message proto.Message, address *goaktpb.Address, cronExpression string) error {
+func (x *scheduler) RemoteScheduleWithCron(ctx context.Context, message proto.Message, address *address.Address, cronExpression string) error {
 	x.mu.Lock()
 	defer x.mu.Unlock()
 
diff --git a/actors/types.go b/actors/types.go
index c3c692a..3d08261 100644
--- a/actors/types.go
+++ b/actors/types.go
@@ -26,8 +26,6 @@ package actors
 
 import (
 	"time"
-
-	"github.com/tochemey/goakt/v2/goaktpb"
 )
 
 const (
@@ -69,8 +67,6 @@ var (
 	NoSender *PID
 	// DefaultSupervisoryStrategy defines the default supervisory strategy
 	DefaultSupervisoryStrategy = NewStopDirective()
-	// RemoteNoSender means that there is no sender
-	RemoteNoSender = new(goaktpb.Address)
 
 	systemNames = map[nameType]string{
 		supervisorType: "GoAktSupervisor",
diff --git a/address/address.go b/address/address.go
new file mode 100644
index 0000000..82f51bd
--- /dev/null
+++ b/address/address.go
@@ -0,0 +1,211 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2022-2024 Tochemey
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package address
+
+import (
+	"bytes"
+	"errors"
+	"net"
+	"strconv"
+	"strings"
+
+	"github.com/google/uuid"
+	"google.golang.org/protobuf/proto"
+
+	"github.com/tochemey/goakt/v2/goaktpb"
+	"github.com/tochemey/goakt/v2/internal/validation"
+)
+
+// protocol defines the Go-Akt addressing protocol
+const protocol = "goakt"
+
+// NoSender means that there is no sender
+var NoSender = new(goaktpb.Address)
+
+type Address struct {
+	*goaktpb.Address
+}
+
+var _ validation.Validator = (*Address)(nil)
+
+// New creates an instance of Address
+func New(name, system string, host string, port int) *Address {
+	return &Address{
+		&goaktpb.Address{
+			Host:   host,
+			Port:   int32(port),
+			Name:   name,
+			Id:     uuid.NewString(),
+			System: system,
+			Parent: NoSender,
+		},
+	}
+}
+
+// From creates an instance of Address provided the serializable address instance
+func From(addr *goaktpb.Address) *Address {
+	return &Address{
+		addr,
+	}
+}
+
+// Default creates an instance of Address with default values.
+func Default() *Address {
+	return &Address{
+		NoSender,
+	}
+}
+
+// WithName sets the name of a given Address and returns the instance of the address
+func (a *Address) WithName(name string) *Address {
+	a.Address.Name = name
+	return a
+}
+
+// WithHost sets the hosts of a given Address and returns the instance of the address
+func (a *Address) WithHost(host string) *Address {
+	a.Address.Host = host
+	return a
+}
+
+// WithPort sets the port of a given Address and returns the instance of the address
+func (a *Address) WithPort(port int) *Address {
+	a.Address.Port = int32(port)
+	return a
+}
+
+// WithSystem sets the actor system of a given Address and returns the instance of the address
+func (a *Address) WithSystem(system string) *Address {
+	a.Address.System = system
+	return a
+}
+
+// WithParent sets the parent of a given Address and returns the instance of the address
+func (a *Address) WithParent(parent *Address) *Address {
+	a.Address.Parent = parent.Address
+	return a
+}
+
+// Parent returns the parent path
+func (a *Address) Parent() *Address {
+	return &Address{a.GetParent()}
+}
+
+// Name returns the name
+func (a *Address) Name() string {
+	return a.GetName()
+}
+
+// Host returns the host
+func (a *Address) Host() string {
+	return a.GetHost()
+}
+
+// Port returns the port number
+func (a *Address) Port() int {
+	return int(a.GetPort())
+}
+
+// System returns the actor system name
+func (a *Address) System() string {
+	return a.GetSystem()
+}
+
+// ID returns actor ID
+func (a *Address) ID() string {
+	return a.GetId()
+}
+
+// String returns the canonical String representation of this Address formatted as:
+// `protocol://system@host:port/name`
+func (a *Address) String() string {
+	buf := bytes.NewBuffer(nil)
+	buf.WriteString(protocol)
+	buf.WriteString("://")
+	buf.WriteString(a.GetSystem())
+	buf.WriteByte('@')
+
+	// write the host and port to the bytes buffer
+	buf.WriteString(a.GetHost())
+	buf.WriteByte(':')
+	buf.WriteString(strconv.Itoa(int(a.GetPort())))
+	buf.WriteString("/")
+	buf.WriteString(a.GetName())
+
+	// returns the constructed string value
+	return buf.String()
+}
+
+// HostPort returns the host and port in the following string format
+// @host:port
+func (a *Address) HostPort() string {
+	// create a bytes buffer instance
+	buf := bytes.NewBuffer(nil)
+	// write the host and port value
+	buf.WriteString(a.GetHost())
+	buf.WriteByte(':')
+	buf.WriteString(strconv.Itoa(int(a.GetPort())))
+	// return the constructed string
+	return buf.String()
+}
+
+// Equals is used to compare two addresses
+func (a *Address) Equals(x *Address) bool {
+	return a.GetId() == x.GetId() && a.String() == x.String()
+}
+
+// MarshalBinary encodes the receiver into a binary form and returns the result.
+func (a *Address) MarshalBinary() (data []byte, err error) {
+	return proto.Marshal(a)
+}
+
+// UnmarshalBinary must be able to decode the form generated by MarshalBinary.
+// UnmarshalBinary must copy the data if it wishes to retain the data after returning.
+func (a *Address) UnmarshalBinary(data []byte) error {
+	pb := new(goaktpb.Address)
+	if err := proto.Unmarshal(data, pb); err != nil {
+		return err
+	}
+	a.Address = pb
+	return nil
+}
+
+// Validate returns an error when the address is not valid
+func (a *Address) Validate() error {
+	if proto.Equal(a.Address, NoSender) {
+		return nil
+	}
+	pattern := "^[a-zA-Z0-9][a-zA-Z0-9-_\\.]*$"
+	customErr := errors.New("must contain only word characters (i.e. [a-zA-Z0-9] plus non-leading '-' or '_')")
+	return validation.
+		New(validation.FailFast()).
+		AddValidator(validation.NewTCPAddressValidator(net.JoinHostPort(a.GetHost(), strconv.Itoa(int(a.GetPort()))))).
+		AddValidator(validation.NewEmptyStringValidator("system", a.GetSystem())).
+		AddValidator(validation.NewEmptyStringValidator("name", a.GetName())).
+		AddValidator(validation.NewPatternValidator(pattern, a.GetSystem(), customErr)).
+		AddValidator(validation.NewPatternValidator(pattern, strings.TrimSpace(a.GetName()), customErr)).
+		AddAssertion(a.Address != nil, "address is required").
+		Validate()
+}
diff --git a/bench/async-comm/main.go b/bench/async-comm/main.go
index a74185f..b1e23ea 100644
--- a/bench/async-comm/main.go
+++ b/bench/async-comm/main.go
@@ -88,8 +88,8 @@ func main() {
 	pingCount := ping.count.Load()
 	pongCount := pong.count.Load()
 
-	logger.Infof("Ping=%s has processed %d messages in %v", pingActor.ActorPath().String(), pingCount, duration)
-	logger.Infof("Pong=%s has processed %d messages in %v", pongActor.ActorPath().String(), pongCount, duration)
+	logger.Infof("Ping=%s has processed %d messages in %v", pingActor.Address().String(), pingCount, duration)
+	logger.Infof("Pong=%s has processed %d messages in %v", pongActor.Address().String(), pongCount, duration)
 
 	logger.Infof("Ping has processed per second: %d", int64(pingCount)/int64(duration.Seconds()))
 	logger.Infof("Pong has processed per second: %d", int64(pongCount)/int64(duration.Seconds()))
diff --git a/client/client.go b/client/client.go
index 3190cec..de5ba25 100644
--- a/client/client.go
+++ b/client/client.go
@@ -38,6 +38,7 @@ import (
 	"google.golang.org/protobuf/proto"
 
 	"github.com/tochemey/goakt/v2/actors"
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/internal/http"
 	"github.com/tochemey/goakt/v2/internal/internalpb"
@@ -208,7 +209,7 @@ func (x *Client) Stop(ctx context.Context, actor *Actor) error {
 }
 
 // Whereis finds and returns the address of a given actor
-func (x *Client) Whereis(ctx context.Context, actor *Actor) (*goaktpb.Address, error) {
+func (x *Client) Whereis(ctx context.Context, actor *Actor) (*address.Address, error) {
 	x.locker.Lock()
 	remoteHost, remotePort := nextRemotingHostAndPort(x.balancer)
 	x.locker.Unlock()
diff --git a/discovery/kubernetes/config.go b/discovery/kubernetes/config.go
index ebcdd64..8df181d 100644
--- a/discovery/kubernetes/config.go
+++ b/discovery/kubernetes/config.go
@@ -34,8 +34,8 @@ type Config struct {
 	Namespace string
 	// ApplicationName specifies the application name
 	ApplicationName string
-	// GossipPortName specifies the gossip port name
-	GossipPortName string
+	// DiscoveryPortName specifies the gossip port name
+	DiscoveryPortName string
 	// RemotingPortName specifies the remoting port name
 	RemotingPortName string
 	// PeersPortName specifies the cluster port name
@@ -49,7 +49,7 @@ func (x Config) Validate() error {
 	return validation.New(validation.FailFast()).
 		AddValidator(validation.NewEmptyStringValidator("Namespace", x.Namespace)).
 		AddValidator(validation.NewEmptyStringValidator("ApplicationName", x.ApplicationName)).
-		AddValidator(validation.NewEmptyStringValidator("GossipPortName", x.GossipPortName)).
+		AddValidator(validation.NewEmptyStringValidator("DiscoveryPortName", x.DiscoveryPortName)).
 		AddValidator(validation.NewEmptyStringValidator("PeersPortName", x.PeersPortName)).
 		AddValidator(validation.NewEmptyStringValidator("RemotingPortName", x.RemotingPortName)).
 		AddValidator(validation.NewEmptyStringValidator("ActorSystemName", x.ActorSystemName)).
diff --git a/discovery/kubernetes/discovery.go b/discovery/kubernetes/discovery.go
index 23aabce..b9e092a 100644
--- a/discovery/kubernetes/discovery.go
+++ b/discovery/kubernetes/discovery.go
@@ -147,7 +147,7 @@ func (d *Discovery) DiscoverPeers() ([]string, error) {
 		return nil, err
 	}
 
-	validPortNames := []string{d.config.PeersPortName, d.config.GossipPortName, d.config.RemotingPortName}
+	validPortNames := []string{d.config.PeersPortName, d.config.DiscoveryPortName, d.config.RemotingPortName}
 
 	// define the addresses list
 	addresses := goset.NewSet[string]()
@@ -174,7 +174,7 @@ MainLoop:
 					continue
 				}
 
-				if port.Name == d.config.GossipPortName {
+				if port.Name == d.config.DiscoveryPortName {
 					addresses.Add(net.JoinHostPort(pod.Status.PodIP, strconv.Itoa(int(port.ContainerPort))))
 				}
 			}
diff --git a/discovery/nats/discovery.go b/discovery/nats/discovery.go
index cd72372..3a720f7 100644
--- a/discovery/nats/discovery.go
+++ b/discovery/nats/discovery.go
@@ -170,7 +170,7 @@ func (d *Discovery) Register() error {
 
 			response := &internalpb.NatsMessage{
 				Host:        d.hostNode.Host,
-				Port:        int32(d.hostNode.GossipPort),
+				Port:        int32(d.hostNode.DiscoveryPort),
 				Name:        d.hostNode.Name,
 				MessageType: internalpb.NatsMessageType_NATS_MESSAGE_TYPE_RESPONSE,
 			}
@@ -224,7 +224,7 @@ func (d *Discovery) Deregister() error {
 		// send a message to deregister stating we are out
 		message := &internalpb.NatsMessage{
 			Host:        d.hostNode.Host,
-			Port:        int32(d.hostNode.GossipPort),
+			Port:        int32(d.hostNode.DiscoveryPort),
 			Name:        d.hostNode.Name,
 			MessageType: internalpb.NatsMessageType_NATS_MESSAGE_TYPE_DEREGISTER,
 		}
@@ -264,7 +264,7 @@ func (d *Discovery) DiscoverPeers() ([]string, error) {
 
 	request := &internalpb.NatsMessage{
 		Host:        d.hostNode.Host,
-		Port:        int32(d.hostNode.GossipPort),
+		Port:        int32(d.hostNode.DiscoveryPort),
 		Name:        d.hostNode.Name,
 		MessageType: internalpb.NatsMessageType_NATS_MESSAGE_TYPE_REQUEST,
 	}
@@ -276,7 +276,7 @@ func (d *Discovery) DiscoverPeers() ([]string, error) {
 
 	var peers []string
 	timeout := time.After(d.config.Timeout)
-	me := d.hostNode.GossipAddress()
+	me := d.hostNode.DiscoveryAddress()
 	for {
 		select {
 		case msg, ok := <-recv:
diff --git a/discovery/node.go b/discovery/node.go
index 6a19e4d..91febd2 100644
--- a/discovery/node.go
+++ b/discovery/node.go
@@ -36,8 +36,8 @@ type Node struct {
 	Name string
 	// Host specifies the discovered node's Host
 	Host string
-	// GossipPort
-	GossipPort int
+	// DiscoveryPort
+	DiscoveryPort int
 	// PeersPort
 	PeersPort int
 	// RemotingPort
@@ -49,12 +49,12 @@ func (n *Node) PeersAddress() string {
 	return net.JoinHostPort(n.Host, strconv.Itoa(n.PeersPort))
 }
 
-// GossipAddress returns the node discovery address
-func (n *Node) GossipAddress() string {
-	return net.JoinHostPort(n.Host, strconv.Itoa(n.GossipPort))
+// DiscoveryAddress returns the node discovery address
+func (n *Node) DiscoveryAddress() string {
+	return net.JoinHostPort(n.Host, strconv.Itoa(n.DiscoveryPort))
 }
 
 // String returns the printable representation of Node
 func (n *Node) String() string {
-	return fmt.Sprintf("[name=%s host=%s gossip=%d  peers=%d remoting=%d]", n.Name, n.Host, n.GossipPort, n.PeersPort, n.RemotingPort)
+	return fmt.Sprintf("[name=%s host=%s gossip=%d  peers=%d remoting=%d]", n.Name, n.Host, n.DiscoveryPort, n.PeersPort, n.RemotingPort)
 }
diff --git a/goaktpb/goakt.pb.go b/goaktpb/goakt.pb.go
index f9facc2..9445f41 100644
--- a/goaktpb/goakt.pb.go
+++ b/goaktpb/goakt.pb.go
@@ -34,8 +34,12 @@ type Address struct {
 	Port int32 `protobuf:"varint,2,opt,name=port,proto3" json:"port,omitempty"`
 	// Specifies the actor name
 	Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
-	// Specifies the actor unique id on the remote host
+	// Specifies the actor unique id
 	Id string `protobuf:"bytes,4,opt,name=id,proto3" json:"id,omitempty"`
+	// Specifies the actor system
+	System string `protobuf:"bytes,5,opt,name=system,proto3" json:"system,omitempty"`
+	// Specifies the parent address
+	Parent *Address `protobuf:"bytes,6,opt,name=parent,proto3" json:"parent,omitempty"`
 }
 
 func (x *Address) Reset() {
@@ -98,6 +102,20 @@ func (x *Address) GetId() string {
 	return ""
 }
 
+func (x *Address) GetSystem() string {
+	if x != nil {
+		return x.System
+	}
+	return ""
+}
+
+func (x *Address) GetParent() *Address {
+	if x != nil {
+		return x.Parent
+	}
+	return nil
+}
+
 // Deadletter defines the deadletter event
 type Deadletter struct {
 	state         protoimpl.MessageState
@@ -729,45 +747,6 @@ func (*PostStart) Descriptor() ([]byte, []int) {
 	return file_goakt_goakt_proto_rawDescGZIP(), []int{11}
 }
 
-// PreStart is used when an actor is about to start
-type PreStart struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-}
-
-func (x *PreStart) Reset() {
-	*x = PreStart{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_goakt_goakt_proto_msgTypes[12]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *PreStart) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*PreStart) ProtoMessage() {}
-
-func (x *PreStart) ProtoReflect() protoreflect.Message {
-	mi := &file_goakt_goakt_proto_msgTypes[12]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use PreStart.ProtoReflect.Descriptor instead.
-func (*PreStart) Descriptor() ([]byte, []int) {
-	return file_goakt_goakt_proto_rawDescGZIP(), []int{12}
-}
-
 // Broadcast is used to send message to a router
 type Broadcast struct {
 	state         protoimpl.MessageState
@@ -781,7 +760,7 @@ type Broadcast struct {
 func (x *Broadcast) Reset() {
 	*x = Broadcast{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_goakt_goakt_proto_msgTypes[13]
+		mi := &file_goakt_goakt_proto_msgTypes[12]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -794,7 +773,7 @@ func (x *Broadcast) String() string {
 func (*Broadcast) ProtoMessage() {}
 
 func (x *Broadcast) ProtoReflect() protoreflect.Message {
-	mi := &file_goakt_goakt_proto_msgTypes[13]
+	mi := &file_goakt_goakt_proto_msgTypes[12]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -807,7 +786,7 @@ func (x *Broadcast) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Broadcast.ProtoReflect.Descriptor instead.
 func (*Broadcast) Descriptor() ([]byte, []int) {
-	return file_goakt_goakt_proto_rawDescGZIP(), []int{13}
+	return file_goakt_goakt_proto_rawDescGZIP(), []int{12}
 }
 
 func (x *Broadcast) GetMessage() *anypb.Any {
@@ -825,98 +804,101 @@ var file_goakt_goakt_proto_rawDesc = []byte{
 	0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e,
 	0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f,
 	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61,
-	0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x55, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72,
-	0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e,
-	0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
-	0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22,
-	0xe5, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x74, 0x74, 0x65, 0x72, 0x12, 0x28,
-	0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10,
-	0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
-	0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x08, 0x72, 0x65, 0x63, 0x65,
-	0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61,
-	0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x08, 0x72, 0x65,
-	0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
-	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x74,
-	0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65,
-	0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12,
-	0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
-	0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x75, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x6f, 0x72,
-	0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
-	0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74,
-	0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72,
-	0x65, 0x73, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61,
-	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
-	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
-	0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x75,
-	0x0a, 0x0c, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x12, 0x2a,
-	0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
-	0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74,
-	0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
-	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
-	0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x6f, 0x70,
-	0x70, 0x65, 0x64, 0x41, 0x74, 0x22, 0x7e, 0x0a, 0x0f, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x61,
-	0x73, 0x73, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
-	0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b,
-	0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64,
-	0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x61, 0x74,
-	0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f,
-	0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69,
-	0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x61,
-	0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x43,
-	0x68, 0x69, 0x6c, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61,
+	0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x97, 0x01, 0x0a, 0x07, 0x41, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04,
+	0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+	0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
+	0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x06, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x28, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74,
+	0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65,
+	0x6e, 0x74, 0x22, 0xe5, 0x01, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x74, 0x74, 0x65,
+	0x72, 0x12, 0x28, 0x0a, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72,
+	0x65, 0x73, 0x73, 0x52, 0x06, 0x73, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x12, 0x2c, 0x0a, 0x08, 0x72,
+	0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
+	0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
+	0x08, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x73,
+	0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79,
+	0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x65, 0x6e,
+	0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67,
+	0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54,
+	0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x08, 0x73, 0x65, 0x6e, 0x64, 0x54, 0x69,
+	0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0x75, 0x0a, 0x0c, 0x41, 0x63,
+	0x74, 0x6f, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f,
+	0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61,
+	0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65,
+	0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
+	0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d,
+	0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41,
+	0x74, 0x22, 0x75, 0x0a, 0x0c, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x53, 0x74, 0x6f, 0x70, 0x70, 0x65,
+	0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x39, 0x0a,
+	0x0a, 0x73, 0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+	0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73,
+	0x74, 0x6f, 0x70, 0x70, 0x65, 0x64, 0x41, 0x74, 0x22, 0x7e, 0x0a, 0x0f, 0x41, 0x63, 0x74, 0x6f,
+	0x72, 0x50, 0x61, 0x73, 0x73, 0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61,
 	0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67,
 	0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07,
-	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e,
-	0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70,
-	0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65, 0x6e,
-	0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
-	0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
-	0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x7b, 0x0a, 0x0e,
-	0x41, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x2a,
+	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3f, 0x0a, 0x0d, 0x70, 0x61, 0x73, 0x73, 0x69,
+	0x76, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
+	0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+	0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x70, 0x61, 0x73, 0x73,
+	0x69, 0x76, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x41, 0x63, 0x74,
+	0x6f, 0x72, 0x43, 0x68, 0x69, 0x6c, 0x64, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2a,
 	0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
 	0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
-	0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x72, 0x65,
-	0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
-	0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
-	0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x72, 0x65,
-	0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x60, 0x0a, 0x0a, 0x4e, 0x6f, 0x64,
-	0x65, 0x4a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
-	0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
-	0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-	0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x5e, 0x0a, 0x08, 0x4e,
-	0x6f, 0x64, 0x65, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
-	0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
-	0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02,
-	0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
-	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
-	0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x27, 0x0a, 0x0a, 0x54,
-	0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x61, 0x63, 0x74,
-	0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x63, 0x74,
-	0x6f, 0x72, 0x49, 0x64, 0x22, 0x0c, 0x0a, 0x0a, 0x50, 0x6f, 0x69, 0x73, 0x6f, 0x6e, 0x50, 0x69,
-	0x6c, 0x6c, 0x22, 0x0b, 0x0a, 0x09, 0x50, 0x6f, 0x73, 0x74, 0x53, 0x74, 0x61, 0x72, 0x74, 0x22,
-	0x0a, 0x0a, 0x08, 0x50, 0x72, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x22, 0x3b, 0x0a, 0x09, 0x42,
-	0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12, 0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73,
-	0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
-	0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52,
-	0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42, 0x85, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d,
-	0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x42, 0x0a, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x50,
-	0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50, 0x01, 0x5a, 0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
-	0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f, 0x67, 0x6f,
-	0x61, 0x6b, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x3b, 0x67,
-	0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x47, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x47,
-	0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0xca, 0x02, 0x07, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62,
-	0xe2, 0x02, 0x13, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65,
-	0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62,
-	0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x28, 0x0a, 0x06, 0x70, 0x61,
+	0x72, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61,
+	0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x06, 0x70, 0x61,
+	0x72, 0x65, 0x6e, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f,
+	0x61, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+	0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
+	0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22,
+	0x7b, 0x0a, 0x0e, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65,
+	0x64, 0x12, 0x2a, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x3d, 0x0a,
+	0x0c, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
+	0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52,
+	0x0b, 0x72, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x60, 0x0a, 0x0a,
+	0x4e, 0x6f, 0x64, 0x65, 0x4a, 0x6f, 0x69, 0x6e, 0x65, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+	0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x5e,
+	0x0a, 0x08, 0x4e, 0x6f, 0x64, 0x65, 0x4c, 0x65, 0x66, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64,
+	0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64,
+	0x72, 0x65, 0x73, 0x73, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+	0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
+	0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x27,
+	0x0a, 0x0a, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08,
+	0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
+	0x61, 0x63, 0x74, 0x6f, 0x72, 0x49, 0x64, 0x22, 0x0c, 0x0a, 0x0a, 0x50, 0x6f, 0x69, 0x73, 0x6f,
+	0x6e, 0x50, 0x69, 0x6c, 0x6c, 0x22, 0x0b, 0x0a, 0x09, 0x50, 0x6f, 0x73, 0x74, 0x53, 0x74, 0x61,
+	0x72, 0x74, 0x22, 0x3b, 0x0a, 0x09, 0x42, 0x72, 0x6f, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x12,
+	0x2e, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
+	0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x42,
+	0x85, 0x01, 0x0a, 0x0b, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x42,
+	0x0a, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50, 0x01, 0x5a,
+	0x2c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f, 0x63, 0x68,
+	0x65, 0x6d, 0x65, 0x79, 0x2f, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x67, 0x6f,
+	0x61, 0x6b, 0x74, 0x70, 0x62, 0x3b, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03,
+	0x47, 0x58, 0x58, 0xaa, 0x02, 0x07, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0xca, 0x02, 0x07,
+	0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0xe2, 0x02, 0x13, 0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70,
+	0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x07,
+	0x47, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -931,7 +913,7 @@ func file_goakt_goakt_proto_rawDescGZIP() []byte {
 	return file_goakt_goakt_proto_rawDescData
 }
 
-var file_goakt_goakt_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
+var file_goakt_goakt_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
 var file_goakt_goakt_proto_goTypes = []any{
 	(*Address)(nil),               // 0: goaktpb.Address
 	(*Deadletter)(nil),            // 1: goaktpb.Deadletter
@@ -945,35 +927,35 @@ var file_goakt_goakt_proto_goTypes = []any{
 	(*Terminated)(nil),            // 9: goaktpb.Terminated
 	(*PoisonPill)(nil),            // 10: goaktpb.PoisonPill
 	(*PostStart)(nil),             // 11: goaktpb.PostStart
-	(*PreStart)(nil),              // 12: goaktpb.PreStart
-	(*Broadcast)(nil),             // 13: goaktpb.Broadcast
-	(*anypb.Any)(nil),             // 14: google.protobuf.Any
-	(*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
+	(*Broadcast)(nil),             // 12: goaktpb.Broadcast
+	(*anypb.Any)(nil),             // 13: google.protobuf.Any
+	(*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp
 }
 var file_goakt_goakt_proto_depIdxs = []int32{
-	0,  // 0: goaktpb.Deadletter.sender:type_name -> goaktpb.Address
-	0,  // 1: goaktpb.Deadletter.receiver:type_name -> goaktpb.Address
-	14, // 2: goaktpb.Deadletter.message:type_name -> google.protobuf.Any
-	15, // 3: goaktpb.Deadletter.send_time:type_name -> google.protobuf.Timestamp
-	0,  // 4: goaktpb.ActorStarted.address:type_name -> goaktpb.Address
-	15, // 5: goaktpb.ActorStarted.started_at:type_name -> google.protobuf.Timestamp
-	0,  // 6: goaktpb.ActorStopped.address:type_name -> goaktpb.Address
-	15, // 7: goaktpb.ActorStopped.stopped_at:type_name -> google.protobuf.Timestamp
-	0,  // 8: goaktpb.ActorPassivated.address:type_name -> goaktpb.Address
-	15, // 9: goaktpb.ActorPassivated.passivated_at:type_name -> google.protobuf.Timestamp
-	0,  // 10: goaktpb.ActorChildCreated.address:type_name -> goaktpb.Address
-	0,  // 11: goaktpb.ActorChildCreated.parent:type_name -> goaktpb.Address
-	15, // 12: goaktpb.ActorChildCreated.created_at:type_name -> google.protobuf.Timestamp
-	0,  // 13: goaktpb.ActorRestarted.address:type_name -> goaktpb.Address
-	15, // 14: goaktpb.ActorRestarted.restarted_at:type_name -> google.protobuf.Timestamp
-	15, // 15: goaktpb.NodeJoined.timestamp:type_name -> google.protobuf.Timestamp
-	15, // 16: goaktpb.NodeLeft.timestamp:type_name -> google.protobuf.Timestamp
-	14, // 17: goaktpb.Broadcast.message:type_name -> google.protobuf.Any
-	18, // [18:18] is the sub-list for method output_type
-	18, // [18:18] is the sub-list for method input_type
-	18, // [18:18] is the sub-list for extension type_name
-	18, // [18:18] is the sub-list for extension extendee
-	0,  // [0:18] is the sub-list for field type_name
+	0,  // 0: goaktpb.Address.parent:type_name -> goaktpb.Address
+	0,  // 1: goaktpb.Deadletter.sender:type_name -> goaktpb.Address
+	0,  // 2: goaktpb.Deadletter.receiver:type_name -> goaktpb.Address
+	13, // 3: goaktpb.Deadletter.message:type_name -> google.protobuf.Any
+	14, // 4: goaktpb.Deadletter.send_time:type_name -> google.protobuf.Timestamp
+	0,  // 5: goaktpb.ActorStarted.address:type_name -> goaktpb.Address
+	14, // 6: goaktpb.ActorStarted.started_at:type_name -> google.protobuf.Timestamp
+	0,  // 7: goaktpb.ActorStopped.address:type_name -> goaktpb.Address
+	14, // 8: goaktpb.ActorStopped.stopped_at:type_name -> google.protobuf.Timestamp
+	0,  // 9: goaktpb.ActorPassivated.address:type_name -> goaktpb.Address
+	14, // 10: goaktpb.ActorPassivated.passivated_at:type_name -> google.protobuf.Timestamp
+	0,  // 11: goaktpb.ActorChildCreated.address:type_name -> goaktpb.Address
+	0,  // 12: goaktpb.ActorChildCreated.parent:type_name -> goaktpb.Address
+	14, // 13: goaktpb.ActorChildCreated.created_at:type_name -> google.protobuf.Timestamp
+	0,  // 14: goaktpb.ActorRestarted.address:type_name -> goaktpb.Address
+	14, // 15: goaktpb.ActorRestarted.restarted_at:type_name -> google.protobuf.Timestamp
+	14, // 16: goaktpb.NodeJoined.timestamp:type_name -> google.protobuf.Timestamp
+	14, // 17: goaktpb.NodeLeft.timestamp:type_name -> google.protobuf.Timestamp
+	13, // 18: goaktpb.Broadcast.message:type_name -> google.protobuf.Any
+	19, // [19:19] is the sub-list for method output_type
+	19, // [19:19] is the sub-list for method input_type
+	19, // [19:19] is the sub-list for extension type_name
+	19, // [19:19] is the sub-list for extension extendee
+	0,  // [0:19] is the sub-list for field type_name
 }
 
 func init() { file_goakt_goakt_proto_init() }
@@ -1127,18 +1109,6 @@ func file_goakt_goakt_proto_init() {
 			}
 		}
 		file_goakt_goakt_proto_msgTypes[12].Exporter = func(v any, i int) any {
-			switch v := v.(*PreStart); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-		file_goakt_goakt_proto_msgTypes[13].Exporter = func(v any, i int) any {
 			switch v := v.(*Broadcast); i {
 			case 0:
 				return &v.state
@@ -1157,7 +1127,7 @@ func file_goakt_goakt_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_goakt_goakt_proto_rawDesc,
 			NumEnums:      0,
-			NumMessages:   14,
+			NumMessages:   13,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/internal/cluster/codec.go b/internal/cluster/codec.go
index ca7b959..521a18a 100644
--- a/internal/cluster/codec.go
+++ b/internal/cluster/codec.go
@@ -32,16 +32,16 @@ import (
 
 // encode marshals a wire actor into a byte array
 // the output of this function can be persisted to the Cluster
-func encode(actor *internalpb.WireActor) ([]byte, error) {
+func encode(actor *internalpb.ActorRef) ([]byte, error) {
 	// let us marshal it
 	bytea, _ := proto.Marshal(actor)
 	return bytea, nil
 }
 
 // decode decodes the encoded base64 representation of a wire actor
-func decode(bytea []byte) (*internalpb.WireActor, error) {
+func decode(bytea []byte) (*internalpb.ActorRef, error) {
 	// create an instance of proto message
-	actor := new(internalpb.WireActor)
+	actor := new(internalpb.ActorRef)
 	// let us unpack the byte array
 	if err := proto.Unmarshal(bytea, actor); err != nil {
 		return nil, err
diff --git a/internal/cluster/engine.go b/internal/cluster/engine.go
index d4c75a2..d5cfc64 100644
--- a/internal/cluster/engine.go
+++ b/internal/cluster/engine.go
@@ -88,9 +88,9 @@ type Interface interface {
 	// RemotingPort returns the cluster remoting port
 	RemotingPort() int
 	// PutActor replicates onto the Node the metadata of an actor
-	PutActor(ctx context.Context, actor *internalpb.WireActor) error
+	PutActor(ctx context.Context, actor *internalpb.ActorRef) error
 	// GetActor fetches an actor from the Node
-	GetActor(ctx context.Context, actorName string) (*internalpb.WireActor, error)
+	GetActor(ctx context.Context, actorName string) (*internalpb.ActorRef, error)
 	// GetPartition returns the partition where a given actor is stored
 	GetPartition(actorName string) int
 	// SetKey sets a given key to the cluster
@@ -216,8 +216,8 @@ func (n *Engine) Start(ctx context.Context) error {
 
 	// sets the bindings
 	m.BindAddr = n.host.Host
-	m.BindPort = n.host.GossipPort
-	m.AdvertisePort = n.host.GossipPort
+	m.BindPort = n.host.DiscoveryPort
+	m.AdvertisePort = n.host.DiscoveryPort
 	conf.MemberlistConfig = m
 
 	// set the discovery provider
@@ -281,7 +281,7 @@ func (n *Engine) Start(ctx context.Context) error {
 		Host:         n.Host(),
 		RemotingPort: int32(n.host.RemotingPort),
 		PeersPort:    int32(n.host.PeersPort),
-		Actors:       []*internalpb.WireActor{},
+		Actors:       []*internalpb.ActorRef{},
 	}
 
 	n.pubSub = ps.Subscribe(ctx, events.ClusterEventsChannel)
@@ -374,7 +374,7 @@ func (n *Engine) AdvertisedAddress() string {
 }
 
 // PutActor pushes to the cluster the peer sync request
-func (n *Engine) PutActor(ctx context.Context, actor *internalpb.WireActor) error {
+func (n *Engine) PutActor(ctx context.Context, actor *internalpb.ActorRef) error {
 	ctx, cancelFn := context.WithTimeout(ctx, n.writeTimeout)
 	defer cancelFn()
 
@@ -390,8 +390,8 @@ func (n *Engine) PutActor(ctx context.Context, actor *internalpb.WireActor) erro
 
 	eg.Go(func() error {
 		encoded, _ := encode(actor)
-		if err := n.dmap.Put(ctx, actor.GetActorName(), encoded); err != nil {
-			return fmt.Errorf("failed to sync actor=(%s) of peer=(%s): %v", actor.GetActorName(), n.host.PeersAddress(), err)
+		if err := n.dmap.Put(ctx, actor.GetActorAddress().GetName(), encoded); err != nil {
+			return fmt.Errorf("failed to sync actor=(%s) of peer=(%s): %v", actor.GetActorAddress().GetName(), n.host.PeersAddress(), err)
 		}
 
 		return nil
@@ -401,7 +401,7 @@ func (n *Engine) PutActor(ctx context.Context, actor *internalpb.WireActor) erro
 		// append to the existing list
 		actors := append(n.peerState.GetActors(), actor)
 		// remove duplicates
-		compacted := slices.CompactFunc(actors, func(actor *internalpb.WireActor, actor2 *internalpb.WireActor) bool {
+		compacted := slices.CompactFunc(actors, func(actor *internalpb.ActorRef, actor2 *internalpb.ActorRef) bool {
 			return proto.Equal(actor, actor2)
 		})
 
@@ -462,7 +462,7 @@ func (n *Engine) GetState(ctx context.Context, peerAddress string) (*internalpb.
 }
 
 // GetActor fetches an actor from the Node
-func (n *Engine) GetActor(ctx context.Context, actorName string) (*internalpb.WireActor, error) {
+func (n *Engine) GetActor(ctx context.Context, actorName string) (*internalpb.ActorRef, error) {
 	ctx, cancelFn := context.WithTimeout(ctx, n.readTimeout)
 	defer cancelFn()
 
@@ -495,7 +495,7 @@ func (n *Engine) GetActor(ctx context.Context, actorName string) (*internalpb.Wi
 		return nil, err
 	}
 
-	logger.Infof("[%s] successfully retrieved from the cluster actor (%s)", n.host.PeersAddress(), actor.GetActorName())
+	logger.Infof("[%s] successfully retrieved from the cluster actor (%s)", n.host.PeersAddress(), actor.GetActorAddress().GetName())
 	return actor, nil
 }
 
diff --git a/internal/internalpb/actor.pb.go b/internal/internalpb/actor.pb.go
new file mode 100644
index 0000000..84f4e62
--- /dev/null
+++ b/internal/internalpb/actor.pb.go
@@ -0,0 +1,171 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.34.2
+// 	protoc        (unknown)
+// source: internal/actor.proto
+
+package internalpb
+
+import (
+	goaktpb "github.com/tochemey/goakt/v2/goaktpb"
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// ActorRef represents the actor information on the wire.
+type ActorRef struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	// Specifies the actor address
+	ActorAddress *goaktpb.Address `protobuf:"bytes,1,opt,name=actor_address,json=actorAddress,proto3" json:"actor_address,omitempty"`
+	// Specifies the actor type
+	ActorType string `protobuf:"bytes,2,opt,name=actor_type,json=actorType,proto3" json:"actor_type,omitempty"`
+}
+
+func (x *ActorRef) Reset() {
+	*x = ActorRef{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_internal_actor_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ActorRef) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ActorRef) ProtoMessage() {}
+
+func (x *ActorRef) ProtoReflect() protoreflect.Message {
+	mi := &file_internal_actor_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ActorRef.ProtoReflect.Descriptor instead.
+func (*ActorRef) Descriptor() ([]byte, []int) {
+	return file_internal_actor_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *ActorRef) GetActorAddress() *goaktpb.Address {
+	if x != nil {
+		return x.ActorAddress
+	}
+	return nil
+}
+
+func (x *ActorRef) GetActorType() string {
+	if x != nil {
+		return x.ActorType
+	}
+	return ""
+}
+
+var File_internal_actor_proto protoreflect.FileDescriptor
+
+var file_internal_actor_proto_rawDesc = []byte{
+	0x0a, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x63, 0x74, 0x6f, 0x72,
+	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
+	0x70, 0x62, 0x1a, 0x11, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2f, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2e,
+	0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x60, 0x0a, 0x08, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x65,
+	0x66, 0x12, 0x35, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65,
+	0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x67, 0x6f, 0x61, 0x6b, 0x74,
+	0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x0c, 0x61, 0x63, 0x74, 0x6f,
+	0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x6f,
+	0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63,
+	0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x42, 0xa3, 0x01, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x42, 0x0a, 0x41, 0x63, 0x74, 0x6f,
+	0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68,
+	0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f,
+	0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
+	0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x3b, 0x69, 0x6e, 0x74,
+	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x0a,
+	0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xca, 0x02, 0x0a, 0x49, 0x6e, 0x74,
+	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xe2, 0x02, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+	0x61, 0x6c, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+	0xea, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70,
+	0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_internal_actor_proto_rawDescOnce sync.Once
+	file_internal_actor_proto_rawDescData = file_internal_actor_proto_rawDesc
+)
+
+func file_internal_actor_proto_rawDescGZIP() []byte {
+	file_internal_actor_proto_rawDescOnce.Do(func() {
+		file_internal_actor_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_actor_proto_rawDescData)
+	})
+	return file_internal_actor_proto_rawDescData
+}
+
+var file_internal_actor_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
+var file_internal_actor_proto_goTypes = []any{
+	(*ActorRef)(nil),        // 0: internalpb.ActorRef
+	(*goaktpb.Address)(nil), // 1: goaktpb.Address
+}
+var file_internal_actor_proto_depIdxs = []int32{
+	1, // 0: internalpb.ActorRef.actor_address:type_name -> goaktpb.Address
+	1, // [1:1] is the sub-list for method output_type
+	1, // [1:1] is the sub-list for method input_type
+	1, // [1:1] is the sub-list for extension type_name
+	1, // [1:1] is the sub-list for extension extendee
+	0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_internal_actor_proto_init() }
+func file_internal_actor_proto_init() {
+	if File_internal_actor_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_internal_actor_proto_msgTypes[0].Exporter = func(v any, i int) any {
+			switch v := v.(*ActorRef); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_internal_actor_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   1,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_internal_actor_proto_goTypes,
+		DependencyIndexes: file_internal_actor_proto_depIdxs,
+		MessageInfos:      file_internal_actor_proto_msgTypes,
+	}.Build()
+	File_internal_actor_proto = out.File
+	file_internal_actor_proto_rawDesc = nil
+	file_internal_actor_proto_goTypes = nil
+	file_internal_actor_proto_depIdxs = nil
+}
diff --git a/internal/internalpb/peers.pb.go b/internal/internalpb/peers.pb.go
index 673ee20..bd31453 100644
--- a/internal/internalpb/peers.pb.go
+++ b/internal/internalpb/peers.pb.go
@@ -34,7 +34,7 @@ type PeersSync struct {
 	// Specifies the remoting host
 	PeersPort int32 `protobuf:"varint,3,opt,name=peers_port,json=peersPort,proto3" json:"peers_port,omitempty"`
 	// Specifies the wire actor
-	Actor *WireActor `protobuf:"bytes,4,opt,name=actor,proto3" json:"actor,omitempty"`
+	Actor *ActorRef `protobuf:"bytes,4,opt,name=actor,proto3" json:"actor,omitempty"`
 }
 
 func (x *PeersSync) Reset() {
@@ -90,7 +90,7 @@ func (x *PeersSync) GetPeersPort() int32 {
 	return 0
 }
 
-func (x *PeersSync) GetActor() *WireActor {
+func (x *PeersSync) GetActor() *ActorRef {
 	if x != nil {
 		return x.Actor
 	}
@@ -109,7 +109,7 @@ type PeerState struct {
 	// Specifies the remoting host
 	PeersPort int32 `protobuf:"varint,3,opt,name=peers_port,json=peersPort,proto3" json:"peers_port,omitempty"`
 	// Specifies the list of actors
-	Actors []*WireActor `protobuf:"bytes,4,rep,name=actors,proto3" json:"actors,omitempty"`
+	Actors []*ActorRef `protobuf:"bytes,4,rep,name=actors,proto3" json:"actors,omitempty"`
 }
 
 func (x *PeerState) Reset() {
@@ -165,7 +165,7 @@ func (x *PeerState) GetPeersPort() int32 {
 	return 0
 }
 
-func (x *PeerState) GetActors() []*WireActor {
+func (x *PeerState) GetActors() []*ActorRef {
 	if x != nil {
 		return x.Actors
 	}
@@ -177,38 +177,37 @@ var File_internal_peers_proto protoreflect.FileDescriptor
 var file_internal_peers_proto_rawDesc = []byte{
 	0x0a, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x65, 0x65, 0x72, 0x73,
 	0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
-	0x70, 0x62, 0x1a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x77, 0x69, 0x72,
-	0x65, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x90, 0x01, 0x0a,
-	0x09, 0x50, 0x65, 0x65, 0x72, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f,
-	0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x23,
-	0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18,
-	0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x50,
-	0x6f, 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x70, 0x6f, 0x72,
-	0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x73, 0x50, 0x6f,
-	0x72, 0x74, 0x12, 0x2b, 0x0a, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28,
-	0x0b, 0x32, 0x15, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x2e, 0x57,
-	0x69, 0x72, 0x65, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x22,
-	0x92, 0x01, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a,
-	0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73,
-	0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f,
-	0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69,
-	0x6e, 0x67, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f,
-	0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72,
-	0x73, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18,
-	0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
-	0x70, 0x62, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x52, 0x06, 0x61, 0x63,
-	0x74, 0x6f, 0x72, 0x73, 0x42, 0xa3, 0x01, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6e, 0x74,
-	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x42, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x73, 0x50, 0x72,
-	0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
-	0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f, 0x67, 0x6f, 0x61,
-	0x6b, 0x74, 0x2f, 0x76, 0x32, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x69,
-	0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
-	0x61, 0x6c, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x0a, 0x49, 0x6e, 0x74,
-	0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xca, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
-	0x61, 0x6c, 0x70, 0x62, 0xe2, 0x02, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70,
-	0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a,
-	0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
-	0x6f, 0x33,
+	0x70, 0x62, 0x1a, 0x14, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x61, 0x63, 0x74,
+	0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8f, 0x01, 0x0a, 0x09, 0x50, 0x65, 0x65,
+	0x72, 0x73, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65,
+	0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x05, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x72, 0x74, 0x12,
+	0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20,
+	0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x2a,
+	0x0a, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x2e, 0x41, 0x63, 0x74, 0x6f, 0x72,
+	0x52, 0x65, 0x66, 0x52, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x22, 0x91, 0x01, 0x0a, 0x09, 0x50,
+	0x65, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d,
+	0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x05, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x69, 0x6e, 0x67, 0x50, 0x6f, 0x72,
+	0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x70, 0x6f, 0x72, 0x74, 0x18,
+	0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x70, 0x65, 0x65, 0x72, 0x73, 0x50, 0x6f, 0x72, 0x74,
+	0x12, 0x2c, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b,
+	0x32, 0x14, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x2e, 0x41, 0x63,
+	0x74, 0x6f, 0x72, 0x52, 0x65, 0x66, 0x52, 0x06, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x73, 0x42, 0xa3,
+	0x01, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70,
+	0x62, 0x42, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02, 0x50,
+	0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x6f,
+	0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2f, 0x76, 0x32, 0x2f,
+	0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61,
+	0x6c, 0x70, 0x62, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xa2, 0x02,
+	0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70,
+	0x62, 0xca, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xe2, 0x02,
+	0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42, 0x4d,
+	0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e,
+	0x61, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -227,11 +226,11 @@ var file_internal_peers_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
 var file_internal_peers_proto_goTypes = []any{
 	(*PeersSync)(nil), // 0: internalpb.PeersSync
 	(*PeerState)(nil), // 1: internalpb.PeerState
-	(*WireActor)(nil), // 2: internalpb.WireActor
+	(*ActorRef)(nil),  // 2: internalpb.ActorRef
 }
 var file_internal_peers_proto_depIdxs = []int32{
-	2, // 0: internalpb.PeersSync.actor:type_name -> internalpb.WireActor
-	2, // 1: internalpb.PeerState.actors:type_name -> internalpb.WireActor
+	2, // 0: internalpb.PeersSync.actor:type_name -> internalpb.ActorRef
+	2, // 1: internalpb.PeerState.actors:type_name -> internalpb.ActorRef
 	2, // [2:2] is the sub-list for method output_type
 	2, // [2:2] is the sub-list for method input_type
 	2, // [2:2] is the sub-list for extension type_name
@@ -244,7 +243,7 @@ func file_internal_peers_proto_init() {
 	if File_internal_peers_proto != nil {
 		return
 	}
-	file_internal_wireactor_proto_init()
+	file_internal_actor_proto_init()
 	if !protoimpl.UnsafeEnabled {
 		file_internal_peers_proto_msgTypes[0].Exporter = func(v any, i int) any {
 			switch v := v.(*PeersSync); i {
diff --git a/internal/internalpb/wireactor.pb.go b/internal/internalpb/wireactor.pb.go
deleted file mode 100644
index c3d4eee..0000000
--- a/internal/internalpb/wireactor.pb.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// 	protoc-gen-go v1.34.2
-// 	protoc        (unknown)
-// source: internal/wireactor.proto
-
-package internalpb
-
-import (
-	goaktpb "github.com/tochemey/goakt/v2/goaktpb"
-	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
-	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
-	reflect "reflect"
-	sync "sync"
-)
-
-const (
-	// Verify that this generated code is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
-	// Verify that runtime/protoimpl is sufficiently up-to-date.
-	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
-
-// WireActor represents the actor information on the wire.
-type WireActor struct {
-	state         protoimpl.MessageState
-	sizeCache     protoimpl.SizeCache
-	unknownFields protoimpl.UnknownFields
-
-	// Specifies the actor name.
-	// The actor name can be either the actor FQN or an alias
-	ActorName string `protobuf:"bytes,1,opt,name=actor_name,json=actorName,proto3" json:"actor_name,omitempty"`
-	// Specifies the actor address
-	ActorAddress *goaktpb.Address `protobuf:"bytes,2,opt,name=actor_address,json=actorAddress,proto3" json:"actor_address,omitempty"`
-	// Specifies the actor full path
-	ActorPath string `protobuf:"bytes,3,opt,name=actor_path,json=actorPath,proto3" json:"actor_path,omitempty"`
-	// Specifies the actor type
-	ActorType string `protobuf:"bytes,4,opt,name=actor_type,json=actorType,proto3" json:"actor_type,omitempty"`
-}
-
-func (x *WireActor) Reset() {
-	*x = WireActor{}
-	if protoimpl.UnsafeEnabled {
-		mi := &file_internal_wireactor_proto_msgTypes[0]
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		ms.StoreMessageInfo(mi)
-	}
-}
-
-func (x *WireActor) String() string {
-	return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WireActor) ProtoMessage() {}
-
-func (x *WireActor) ProtoReflect() protoreflect.Message {
-	mi := &file_internal_wireactor_proto_msgTypes[0]
-	if protoimpl.UnsafeEnabled && x != nil {
-		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
-		if ms.LoadMessageInfo() == nil {
-			ms.StoreMessageInfo(mi)
-		}
-		return ms
-	}
-	return mi.MessageOf(x)
-}
-
-// Deprecated: Use WireActor.ProtoReflect.Descriptor instead.
-func (*WireActor) Descriptor() ([]byte, []int) {
-	return file_internal_wireactor_proto_rawDescGZIP(), []int{0}
-}
-
-func (x *WireActor) GetActorName() string {
-	if x != nil {
-		return x.ActorName
-	}
-	return ""
-}
-
-func (x *WireActor) GetActorAddress() *goaktpb.Address {
-	if x != nil {
-		return x.ActorAddress
-	}
-	return nil
-}
-
-func (x *WireActor) GetActorPath() string {
-	if x != nil {
-		return x.ActorPath
-	}
-	return ""
-}
-
-func (x *WireActor) GetActorType() string {
-	if x != nil {
-		return x.ActorType
-	}
-	return ""
-}
-
-var File_internal_wireactor_proto protoreflect.FileDescriptor
-
-var file_internal_wireactor_proto_rawDesc = []byte{
-	0x0a, 0x18, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x77, 0x69, 0x72, 0x65, 0x61,
-	0x63, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x69, 0x6e, 0x74, 0x65,
-	0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x1a, 0x11, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2f, 0x67, 0x6f,
-	0x61, 0x6b, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x9f, 0x01, 0x0a, 0x09, 0x57, 0x69,
-	0x72, 0x65, 0x41, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x74, 0x6f, 0x72,
-	0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x74,
-	0x6f, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x0d, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f,
-	0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e,
-	0x67, 0x6f, 0x61, 0x6b, 0x74, 0x70, 0x62, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
-	0x0c, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1d, 0x0a,
-	0x0a, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28,
-	0x09, 0x52, 0x09, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1d, 0x0a, 0x0a,
-	0x61, 0x63, 0x74, 0x6f, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09,
-	0x52, 0x09, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x42, 0xa7, 0x01, 0x0a, 0x0e,
-	0x63, 0x6f, 0x6d, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x42, 0x0e,
-	0x57, 0x69, 0x72, 0x65, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x48, 0x02,
-	0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74,
-	0x6f, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x79, 0x2f, 0x67, 0x6f, 0x61, 0x6b, 0x74, 0x2f, 0x76, 0x32,
-	0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
-	0x61, 0x6c, 0x70, 0x62, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xa2,
-	0x02, 0x03, 0x49, 0x58, 0x58, 0xaa, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c,
-	0x70, 0x62, 0xca, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0xe2,
-	0x02, 0x16, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x70, 0x62, 0x5c, 0x47, 0x50, 0x42,
-	0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x49, 0x6e, 0x74, 0x65, 0x72,
-	0x6e, 0x61, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
-}
-
-var (
-	file_internal_wireactor_proto_rawDescOnce sync.Once
-	file_internal_wireactor_proto_rawDescData = file_internal_wireactor_proto_rawDesc
-)
-
-func file_internal_wireactor_proto_rawDescGZIP() []byte {
-	file_internal_wireactor_proto_rawDescOnce.Do(func() {
-		file_internal_wireactor_proto_rawDescData = protoimpl.X.CompressGZIP(file_internal_wireactor_proto_rawDescData)
-	})
-	return file_internal_wireactor_proto_rawDescData
-}
-
-var file_internal_wireactor_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
-var file_internal_wireactor_proto_goTypes = []any{
-	(*WireActor)(nil),       // 0: internalpb.WireActor
-	(*goaktpb.Address)(nil), // 1: goaktpb.Address
-}
-var file_internal_wireactor_proto_depIdxs = []int32{
-	1, // 0: internalpb.WireActor.actor_address:type_name -> goaktpb.Address
-	1, // [1:1] is the sub-list for method output_type
-	1, // [1:1] is the sub-list for method input_type
-	1, // [1:1] is the sub-list for extension type_name
-	1, // [1:1] is the sub-list for extension extendee
-	0, // [0:1] is the sub-list for field type_name
-}
-
-func init() { file_internal_wireactor_proto_init() }
-func file_internal_wireactor_proto_init() {
-	if File_internal_wireactor_proto != nil {
-		return
-	}
-	if !protoimpl.UnsafeEnabled {
-		file_internal_wireactor_proto_msgTypes[0].Exporter = func(v any, i int) any {
-			switch v := v.(*WireActor); i {
-			case 0:
-				return &v.state
-			case 1:
-				return &v.sizeCache
-			case 2:
-				return &v.unknownFields
-			default:
-				return nil
-			}
-		}
-	}
-	type x struct{}
-	out := protoimpl.TypeBuilder{
-		File: protoimpl.DescBuilder{
-			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
-			RawDescriptor: file_internal_wireactor_proto_rawDesc,
-			NumEnums:      0,
-			NumMessages:   1,
-			NumExtensions: 0,
-			NumServices:   0,
-		},
-		GoTypes:           file_internal_wireactor_proto_goTypes,
-		DependencyIndexes: file_internal_wireactor_proto_depIdxs,
-		MessageInfos:      file_internal_wireactor_proto_msgTypes,
-	}.Build()
-	File_internal_wireactor_proto = out.File
-	file_internal_wireactor_proto_rawDesc = nil
-	file_internal_wireactor_proto_goTypes = nil
-	file_internal_wireactor_proto_depIdxs = nil
-}
diff --git a/internal/validation/tcp_address.go b/internal/validation/tcp_address.go
index cc2c0ef..9ed10e6 100644
--- a/internal/validation/tcp_address.go
+++ b/internal/validation/tcp_address.go
@@ -61,7 +61,7 @@ func (a *TCPAddressValidator) Validate() error {
 	}
 
 	// TODO: maybe we only need to check port number not to be negative
-	if host == "" || portNum > 65535 || portNum < 1 {
+	if host == "" || portNum > 65535 || portNum < 0 {
 		return fmt.Errorf(errFmt, a.address, errors.New("invalid address"))
 	}
 
diff --git a/mocks/cluster/interface.go b/mocks/cluster/interface.go
index 5de05e4..9c25f55 100644
--- a/mocks/cluster/interface.go
+++ b/mocks/cluster/interface.go
@@ -117,23 +117,23 @@ func (_c *Interface_Events_Call) RunAndReturn(run func() <-chan *internalcluster
 }
 
 // GetActor provides a mock function with given fields: ctx, actorName
-func (_m *Interface) GetActor(ctx context.Context, actorName string) (*internalpb.WireActor, error) {
+func (_m *Interface) GetActor(ctx context.Context, actorName string) (*internalpb.ActorRef, error) {
 	ret := _m.Called(ctx, actorName)
 
 	if len(ret) == 0 {
 		panic("no return value specified for GetActor")
 	}
 
-	var r0 *internalpb.WireActor
+	var r0 *internalpb.ActorRef
 	var r1 error
-	if rf, ok := ret.Get(0).(func(context.Context, string) (*internalpb.WireActor, error)); ok {
+	if rf, ok := ret.Get(0).(func(context.Context, string) (*internalpb.ActorRef, error)); ok {
 		return rf(ctx, actorName)
 	}
-	if rf, ok := ret.Get(0).(func(context.Context, string) *internalpb.WireActor); ok {
+	if rf, ok := ret.Get(0).(func(context.Context, string) *internalpb.ActorRef); ok {
 		r0 = rf(ctx, actorName)
 	} else {
 		if ret.Get(0) != nil {
-			r0 = ret.Get(0).(*internalpb.WireActor)
+			r0 = ret.Get(0).(*internalpb.ActorRef)
 		}
 	}
 
@@ -165,12 +165,12 @@ func (_c *Interface_GetActor_Call) Run(run func(ctx context.Context, actorName s
 	return _c
 }
 
-func (_c *Interface_GetActor_Call) Return(_a0 *internalpb.WireActor, _a1 error) *Interface_GetActor_Call {
+func (_c *Interface_GetActor_Call) Return(_a0 *internalpb.ActorRef, _a1 error) *Interface_GetActor_Call {
 	_c.Call.Return(_a0, _a1)
 	return _c
 }
 
-func (_c *Interface_GetActor_Call) RunAndReturn(run func(context.Context, string) (*internalpb.WireActor, error)) *Interface_GetActor_Call {
+func (_c *Interface_GetActor_Call) RunAndReturn(run func(context.Context, string) (*internalpb.ActorRef, error)) *Interface_GetActor_Call {
 	_c.Call.Return(run)
 	return _c
 }
@@ -487,7 +487,7 @@ func (_c *Interface_Peers_Call) RunAndReturn(run func(context.Context) ([]*inter
 }
 
 // PutActor provides a mock function with given fields: ctx, actor
-func (_m *Interface) PutActor(ctx context.Context, actor *internalpb.WireActor) error {
+func (_m *Interface) PutActor(ctx context.Context, actor *internalpb.ActorRef) error {
 	ret := _m.Called(ctx, actor)
 
 	if len(ret) == 0 {
@@ -495,7 +495,7 @@ func (_m *Interface) PutActor(ctx context.Context, actor *internalpb.WireActor)
 	}
 
 	var r0 error
-	if rf, ok := ret.Get(0).(func(context.Context, *internalpb.WireActor) error); ok {
+	if rf, ok := ret.Get(0).(func(context.Context, *internalpb.ActorRef) error); ok {
 		r0 = rf(ctx, actor)
 	} else {
 		r0 = ret.Error(0)
@@ -511,14 +511,14 @@ type Interface_PutActor_Call struct {
 
 // PutActor is a helper method to define mock.On call
 //   - ctx context.Context
-//   - actor *internalpb.WireActor
+//   - actor *internalpb.ActorRef
 func (_e *Interface_Expecter) PutActor(ctx interface{}, actor interface{}) *Interface_PutActor_Call {
 	return &Interface_PutActor_Call{Call: _e.mock.On("PutActor", ctx, actor)}
 }
 
-func (_c *Interface_PutActor_Call) Run(run func(ctx context.Context, actor *internalpb.WireActor)) *Interface_PutActor_Call {
+func (_c *Interface_PutActor_Call) Run(run func(ctx context.Context, actor *internalpb.ActorRef)) *Interface_PutActor_Call {
 	_c.Call.Run(func(args mock.Arguments) {
-		run(args[0].(context.Context), args[1].(*internalpb.WireActor))
+		run(args[0].(context.Context), args[1].(*internalpb.ActorRef))
 	})
 	return _c
 }
@@ -528,7 +528,7 @@ func (_c *Interface_PutActor_Call) Return(_a0 error) *Interface_PutActor_Call {
 	return _c
 }
 
-func (_c *Interface_PutActor_Call) RunAndReturn(run func(context.Context, *internalpb.WireActor) error) *Interface_PutActor_Call {
+func (_c *Interface_PutActor_Call) RunAndReturn(run func(context.Context, *internalpb.ActorRef) error) *Interface_PutActor_Call {
 	_c.Call.Return(run)
 	return _c
 }
diff --git a/protos/goakt/goakt.proto b/protos/goakt/goakt.proto
index 99fee3d..4eaabc8 100644
--- a/protos/goakt/goakt.proto
+++ b/protos/goakt/goakt.proto
@@ -15,8 +15,12 @@ message Address {
   int32 port = 2;
   // Specifies the actor name
   string name = 3;
-  // Specifies the actor unique id on the remote host
+  // Specifies the actor unique id
   string id = 4;
+  // Specifies the actor system
+  string system = 5;
+  // Specifies the parent address
+  Address parent = 6;
 }
 
 // Deadletter defines the deadletter event
@@ -107,9 +111,6 @@ message PoisonPill {}
 // PostStart is used when an actor has successfully started
 message PostStart {}
 
-// PreStart is used when an actor is about to start
-message PreStart {}
-
 // Broadcast is used to send message to a router
 message Broadcast {
   // Specifies the actual message
diff --git a/protos/internal/actor.proto b/protos/internal/actor.proto
new file mode 100644
index 0000000..ea8a2e0
--- /dev/null
+++ b/protos/internal/actor.proto
@@ -0,0 +1,15 @@
+syntax = "proto3";
+
+package internalpb;
+
+import "goakt/goakt.proto";
+
+option go_package = "github.com/tochemey/goakt/v2/internal/internalpb;internalpb";
+
+// ActorRef represents the actor information on the wire.
+message ActorRef {
+  // Specifies the actor address
+  goaktpb.Address actor_address = 1;
+  // Specifies the actor type
+  string actor_type = 2;
+}
diff --git a/protos/internal/peers.proto b/protos/internal/peers.proto
index 5925fa7..20a9d3b 100644
--- a/protos/internal/peers.proto
+++ b/protos/internal/peers.proto
@@ -2,7 +2,7 @@ syntax = "proto3";
 
 package internalpb;
 
-import "internal/wireactor.proto";
+import "internal/actor.proto";
 
 option go_package = "github.com/tochemey/goakt/v2/internal/internalpb;internalpb";
 
@@ -16,7 +16,7 @@ message PeersSync {
   // Specifies the remoting host
   int32 peers_port = 3;
   // Specifies the wire actor
-  WireActor actor = 4;
+  ActorRef actor = 4;
 }
 
 message PeerState {
@@ -27,5 +27,5 @@ message PeerState {
   // Specifies the remoting host
   int32 peers_port = 3;
   // Specifies the list of actors
-  repeated WireActor actors = 4;
+  repeated ActorRef actors = 4;
 }
diff --git a/protos/internal/wireactor.proto b/protos/internal/wireactor.proto
deleted file mode 100644
index 6fe1192..0000000
--- a/protos/internal/wireactor.proto
+++ /dev/null
@@ -1,20 +0,0 @@
-syntax = "proto3";
-
-package internalpb;
-
-import "goakt/goakt.proto";
-
-option go_package = "github.com/tochemey/goakt/v2/internal/internalpb;internalpb";
-
-// WireActor represents the actor information on the wire.
-message WireActor {
-  // Specifies the actor name.
-  // The actor name can be either the actor FQN or an alias
-  string actor_name = 1;
-  // Specifies the actor address
-  goaktpb.Address actor_address = 2;
-  // Specifies the actor full path
-  string actor_path = 3;
-  // Specifies the actor type
-  string actor_type = 4;
-}
diff --git a/telemetry/option.go b/telemetry/option.go
index 37fbe4c..2f2b235 100644
--- a/telemetry/option.go
+++ b/telemetry/option.go
@@ -48,7 +48,7 @@ func (f OptionFunc) Apply(c *Telemetry) {
 // If none is specified, the global provider is used.
 func WithTracerProvider(provider trace.TracerProvider) Option {
 	return OptionFunc(func(cfg *Telemetry) {
-		cfg.TracerProvider = provider
+		cfg.tracerProvider = provider
 	})
 }
 
@@ -56,6 +56,6 @@ func WithTracerProvider(provider trace.TracerProvider) Option {
 // If none is specified, the global provider is used.
 func WithMeterProvider(provider metric.MeterProvider) Option {
 	return OptionFunc(func(cfg *Telemetry) {
-		cfg.MeterProvider = provider
+		cfg.meterProvider = provider
 	})
 }
diff --git a/telemetry/telemetry.go b/telemetry/telemetry.go
index 73129cc..727839a 100644
--- a/telemetry/telemetry.go
+++ b/telemetry/telemetry.go
@@ -36,19 +36,19 @@ const (
 
 // Telemetry encapsulates some settings for an actor
 type Telemetry struct {
-	TracerProvider trace.TracerProvider
-	Tracer         trace.Tracer
+	tracerProvider trace.TracerProvider
+	tracer         trace.Tracer
 
-	MeterProvider metric.MeterProvider
-	Meter         metric.Meter
+	meterProvider metric.MeterProvider
+	meter         metric.Meter
 }
 
 // New creates an instance of Telemetry
 func New(options ...Option) *Telemetry {
 	// create a config instance
 	telemetry := &Telemetry{
-		TracerProvider: otel.GetTracerProvider(),
-		MeterProvider:  otel.GetMeterProvider(),
+		tracerProvider: otel.GetTracerProvider(),
+		meterProvider:  otel.GetMeterProvider(),
 	}
 
 	// apply the various options
@@ -57,16 +57,36 @@ func New(options ...Option) *Telemetry {
 	}
 
 	// set the tracer
-	telemetry.Tracer = telemetry.TracerProvider.Tracer(
+	telemetry.tracer = telemetry.tracerProvider.Tracer(
 		instrumentationName,
 		trace.WithInstrumentationVersion(Version()),
 	)
 
 	// set the meter
-	telemetry.Meter = telemetry.MeterProvider.Meter(
+	telemetry.meter = telemetry.meterProvider.Meter(
 		instrumentationName,
 		metric.WithInstrumentationVersion(Version()),
 	)
 
 	return telemetry
 }
+
+// TraceProvider returns the trace provider
+func (t *Telemetry) TraceProvider() trace.TracerProvider {
+	return t.tracerProvider
+}
+
+// MeterProvider returns the meter provider
+func (t *Telemetry) MeterProvider() metric.MeterProvider {
+	return t.meterProvider
+}
+
+// Meter returns the meter
+func (t *Telemetry) Meter() metric.Meter {
+	return t.meter
+}
+
+// Tracer returns the tracer
+func (t *Telemetry) Tracer() trace.Tracer {
+	return t.tracer
+}


Test patch:
diff --git a/actors/actor_system_test.go b/actors/actor_system_test.go
index e0919ec..271eef1 100644
--- a/actors/actor_system_test.go
+++ b/actors/actor_system_test.go
@@ -26,7 +26,6 @@ package actors
 
 import (
 	"context"
-	"fmt"
 	"net"
 	"sort"
 	"strconv"
@@ -44,6 +43,7 @@ import (
 	"go.uber.org/atomic"
 	"google.golang.org/protobuf/proto"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/internal/types"
 	"github.com/tochemey/goakt/v2/log"
@@ -119,7 +119,7 @@ func TestActorSystem(t *testing.T) {
 		actor := newTestActor()
 		actorRef, err := sys.Spawn(ctx, "$omeN@me", actor)
 		require.Error(t, err)
-		assert.EqualError(t, err, "path name must contain only word characters (i.e. [a-zA-Z0-9] plus non-leading '-' or '_')")
+		assert.EqualError(t, err, "must contain only word characters (i.e. [a-zA-Z0-9] plus non-leading '-' or '_')")
 		assert.Nil(t, actorRef)
 
 		// stop the actor after some time
@@ -303,7 +303,7 @@ func TestActorSystem(t *testing.T) {
 		addr, pid, err := sys.ActorOf(ctx, actorName)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
-		require.Nil(t, addr)
+		require.NotNil(t, addr)
 
 		// stop the actor after some time
 		pause(time.Second)
@@ -592,12 +592,13 @@ func TestActorSystem(t *testing.T) {
 		require.Nil(t, addr)
 
 		// attempt to send a message will fail
-		reply, err := RemoteAsk(ctx, &goaktpb.Address{
+		addr = address.From(&goaktpb.Address{
 			Host: host,
 			Port: int32(remotingPort),
 			Name: actorName,
 			Id:   "",
-		}, new(testpb.TestReply), DefaultAskTimeout)
+		})
+		reply, err := RemoteAsk(ctx, addr, new(testpb.TestReply), DefaultAskTimeout)
 		require.Error(t, err)
 		require.Nil(t, reply)
 
@@ -702,7 +703,7 @@ func TestActorSystem(t *testing.T) {
 		require.NoError(t, err)
 		require.NotNil(t, local)
 
-		require.Equal(t, ref.ActorPath().String(), local.ActorPath().String())
+		require.Equal(t, ref.Address().String(), local.Address().String())
 
 		// stop the actor after some time
 		pause(time.Second)
@@ -762,7 +763,7 @@ func TestActorSystem(t *testing.T) {
 		assert.NoError(t, err)
 		err = sys.Kill(ctx, "Test")
 		assert.Error(t, err)
-		assert.EqualError(t, err, "actor=goakt://testSys@/Test not found")
+		assert.EqualError(t, err, "actor=goakt://testSys@127.0.0.1:0/Test not found")
 		t.Cleanup(func() {
 			err = sys.Stop(ctx)
 			assert.NoError(t, err)
@@ -1485,78 +1486,4 @@ func TestActorSystem(t *testing.T) {
 			assert.NoError(t, err)
 		})
 	})
-	t.Run("With actors redeployment", func(t *testing.T) {
-		// create a context
-		ctx := context.TODO()
-		// start the NATS server
-		srv := startNatsServer(t)
-
-		// create and start system cluster
-		node1, sd1 := startClusterSystem(t, "Node1", srv.Addr().String())
-		require.NotNil(t, node1)
-		require.NotNil(t, sd1)
-
-		// create and start system cluster
-		node2, sd2 := startClusterSystem(t, "Node2", srv.Addr().String())
-		require.NotNil(t, node2)
-		require.NotNil(t, sd2)
-
-		// create and start system cluster
-		node3, sd3 := startClusterSystem(t, "Node3", srv.Addr().String())
-		require.NotNil(t, node3)
-		require.NotNil(t, sd3)
-
-		// let us create 4 actors on each node
-		for j := 1; j <= 4; j++ {
-			actorName := fmt.Sprintf("Node1-Actor-%d", j)
-			pid, err := node1.Spawn(ctx, actorName, newTestActor())
-			require.NoError(t, err)
-			require.NotNil(t, pid)
-		}
-
-		pause(time.Second)
-
-		for j := 1; j <= 4; j++ {
-			actorName := fmt.Sprintf("Node2-Actor-%d", j)
-			pid, err := node2.Spawn(ctx, actorName, newTestActor())
-			require.NoError(t, err)
-			require.NotNil(t, pid)
-		}
-
-		pause(time.Second)
-
-		for j := 1; j <= 4; j++ {
-			actorName := fmt.Sprintf("Node3-Actor-%d", j)
-			pid, err := node3.Spawn(ctx, actorName, newTestActor())
-			require.NoError(t, err)
-			require.NotNil(t, pid)
-		}
-
-		pause(time.Second)
-
-		// take down node2
-		require.NoError(t, node2.Stop(ctx))
-		require.NoError(t, sd2.Close())
-
-		// Wait for cluster rebalancing
-		pause(time.Minute)
-
-		// let us access some of the node2 actors from node 1 and  node 3
-		actorName := "Node2-Actor-1"
-
-		sender, err := node1.LocalActor("Node1-Actor-1")
-		require.NoError(t, err)
-		require.NotNil(t, sender)
-
-		err = sender.SendAsync(ctx, actorName, new(testpb.TestSend))
-		require.NoError(t, err)
-
-		t.Cleanup(func() {
-			assert.NoError(t, node1.Stop(ctx))
-			assert.NoError(t, node3.Stop(ctx))
-			assert.NoError(t, sd1.Close())
-			assert.NoError(t, sd3.Close())
-			srv.Shutdown()
-		})
-	})
 }
diff --git a/actors/api_test.go b/actors/api_test.go
index 509f238..c7b90b0 100644
--- a/actors/api_test.go
+++ b/actors/api_test.go
@@ -36,6 +36,7 @@ import (
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/types/known/anypb"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/internal/internalpb"
 	"github.com/tochemey/goakt/v2/log"
@@ -649,7 +650,7 @@ func TestRemoteTell(t *testing.T) {
 		// create a message to send to the test actor
 		message := new(testpb.TestSend)
 		// send the message to the actor
-		err = RemoteTell(ctx, addr, message)
+		err = RemoteTell(ctx, address.From(addr), message)
 		// perform some assertions
 		require.Error(t, err)
 
@@ -809,7 +810,7 @@ func TestRemoteTell(t *testing.T) {
 		// create a message to send to the test actor
 		message := new(testpb.TestSend)
 		// send the message to the actor
-		err = RemoteBatchTell(ctx, addr, message)
+		err = RemoteBatchTell(ctx, address.From(addr), message)
 		// perform some assertions
 		require.Error(t, err)
 
@@ -1132,7 +1133,7 @@ func TestRemoteAsk(t *testing.T) {
 		// create a message to send to the test actor
 		message := new(testpb.TestReply)
 		// send the message to the actor
-		reply, err := RemoteAsk(ctx, addr, message, time.Minute)
+		reply, err := RemoteAsk(ctx, address.From(addr), message, time.Minute)
 		// perform some assertions
 		require.Error(t, err)
 		require.Nil(t, reply)
@@ -1300,7 +1301,7 @@ func TestRemoteAsk(t *testing.T) {
 		// create a message to send to the test actor
 		message := new(testpb.TestReply)
 		// send the message to the actor
-		reply, err := RemoteBatchAsk(ctx, addr, message)
+		reply, err := RemoteBatchAsk(ctx, address.From(addr), message)
 		// perform some assertions
 		require.Error(t, err)
 		require.Nil(t, reply)
diff --git a/actors/cluster_config_test.go b/actors/cluster_config_test.go
index dabe9db..184632c 100644
--- a/actors/cluster_config_test.go
+++ b/actors/cluster_config_test.go
@@ -42,7 +42,7 @@ func TestClusterConfig(t *testing.T) {
 		kinds := []Actor{tester, exchanger}
 		config := NewClusterConfig().
 			WithKinds(kinds...).
-			WithGossipPort(3220).
+			WithDiscoveryPort(3220).
 			WithPeersPort(3222).
 			WithMinimumPeersQuorum(1).
 			WithReplicaCount(1).
@@ -50,7 +50,7 @@ func TestClusterConfig(t *testing.T) {
 			WithDiscovery(disco)
 
 		require.NoError(t, config.Validate())
-		assert.EqualValues(t, 3220, config.GossipPort())
+		assert.EqualValues(t, 3220, config.DiscoveryPort())
 		assert.EqualValues(t, 3222, config.PeersPort())
 		assert.EqualValues(t, 1, config.MinimumPeersQuorum())
 		assert.EqualValues(t, 1, config.ReplicaCount())
@@ -62,7 +62,7 @@ func TestClusterConfig(t *testing.T) {
 	t.Run("With invalid config setting", func(t *testing.T) {
 		config := NewClusterConfig().
 			WithKinds(new(exchanger), new(testActor)).
-			WithGossipPort(3220).
+			WithDiscoveryPort(3220).
 			WithPeersPort(3222).
 			WithMinimumPeersQuorum(1).
 			WithReplicaCount(1).
diff --git a/actors/helper_test.go b/actors/helper_test.go
index 00307ae..0f48a7a 100644
--- a/actors/helper_test.go
+++ b/actors/helper_test.go
@@ -453,11 +453,11 @@ func startClusterSystem(t *testing.T, nodeName, serverAddr string) (ActorSystem,
 	}
 
 	hostNode := discovery.Node{
-		Name:         nodeName,
-		Host:         host,
-		GossipPort:   gossipPort,
-		PeersPort:    clusterPort,
-		RemotingPort: remotingPort,
+		Name:          nodeName,
+		Host:          host,
+		DiscoveryPort: gossipPort,
+		PeersPort:     clusterPort,
+		RemotingPort:  remotingPort,
 	}
 
 	// create the instance of provider
@@ -478,7 +478,7 @@ func startClusterSystem(t *testing.T, nodeName, serverAddr string) (ActorSystem,
 				WithReplicaCount(1).
 				WithPeersPort(clusterPort).
 				WithMinimumPeersQuorum(1).
-				WithGossipPort(gossipPort).
+				WithDiscoveryPort(gossipPort).
 				WithDiscovery(provider).WithKinds(new(testActor))),
 	)
 
diff --git a/actors/option_test.go b/actors/option_test.go
index 6002674..8e5e0d8 100644
--- a/actors/option_test.go
+++ b/actors/option_test.go
@@ -81,7 +81,7 @@ func TestOption(t *testing.T) {
 		{
 			name:     "WithRemoting",
 			option:   WithRemoting("localhost", 3100),
-			expected: actorSystem{remotingEnabled: atomicTrue, remotingPort: 3100, remotingHost: "localhost"},
+			expected: actorSystem{remotingEnabled: atomicTrue, port: 3100, host: "localhost"},
 		},
 		{
 			name:     "WithShutdownTimeout",
diff --git a/actors/pid_map_test.go b/actors/pid_map_test.go
index 0b37e35..9f4243e 100644
--- a/actors/pid_map_test.go
+++ b/actors/pid_map_test.go
@@ -29,13 +29,17 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/travisjeffery/go-dynaport"
+
+	"github.com/tochemey/goakt/v2/address"
 )
 
 func TestPIDMap(t *testing.T) {
+	ports := dynaport.Get(1)
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("TestSys", "host", 444))
+	actorPath := address.New("Test", "TestSys", "host", ports[0])
 	// create the PID
-	actorRef := &PID{actorPath: actorPath, fieldsLocker: &sync.RWMutex{}, stopLocker: &sync.Mutex{}}
+	actorRef := &PID{address: actorPath, fieldsLocker: &sync.RWMutex{}, stopLocker: &sync.Mutex{}}
 	// create a new PID map
 	pidMap := newPIDMap(5)
 	// add to the map
diff --git a/actors/pid_test.go b/actors/pid_test.go
index fd42449..ccd9cb1 100644
--- a/actors/pid_test.go
+++ b/actors/pid_test.go
@@ -40,6 +40,7 @@ import (
 	"go.opentelemetry.io/otel/sdk/metric/metricdata"
 	"google.golang.org/protobuf/proto"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/internal/eventstream"
 	"github.com/tochemey/goakt/v2/log"
@@ -56,9 +57,9 @@ const (
 
 func TestReceive(t *testing.T) {
 	ctx := context.TODO()
-
+	ports := dynaport.Get(1)
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -98,8 +99,10 @@ func TestPassivation(t *testing.T) {
 			withAskTimeout(replyTimeout),
 		}
 
+		ports := dynaport.Get(1)
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		actorPath := address.New("Test", "sys", "host", ports[0])
+
 		pid, err := newPID(ctx, actorPath, newTestActor(), opts...)
 		require.NoError(t, err)
 		assert.NotNil(t, pid)
@@ -127,8 +130,10 @@ func TestPassivation(t *testing.T) {
 			withAskTimeout(replyTimeout),
 		}
 
+		ports := dynaport.Get(1)
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		actorPath := address.New("Test", "sys", "host", ports[0])
+
 		pid, err := newPID(ctx, actorPath, &testPostStop{}, opts...)
 		require.NoError(t, err)
 		assert.NotNil(t, pid)
@@ -158,7 +163,10 @@ func TestReply(t *testing.T) {
 		}
 
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
+
 		pid, err := newPID(ctx, actorPath, newTestActor(), opts...)
 
 		require.NoError(t, err)
@@ -182,7 +190,9 @@ func TestReply(t *testing.T) {
 		}
 
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, newTestActor(), opts...)
 
 		require.NoError(t, err)
@@ -205,7 +215,9 @@ func TestReply(t *testing.T) {
 		}
 
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, newTestActor(), opts...)
 
 		require.NoError(t, err)
@@ -230,7 +242,9 @@ func TestRestart(t *testing.T) {
 		assert.NotNil(t, actor)
 
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		// create the actor ref
 		pid, err := newPID(ctx, actorPath, actor,
 			withInitMaxRetries(1),
@@ -274,7 +288,9 @@ func TestRestart(t *testing.T) {
 		actor := newTestActor()
 		assert.NotNil(t, actor)
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the actor ref
 		pid, err := newPID(ctx, actorPath, actor,
@@ -312,7 +328,9 @@ func TestRestart(t *testing.T) {
 		actor := newTestRestart()
 		assert.NotNil(t, actor)
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the actor ref
 		pid, err := newPID(ctx, actorPath, actor,
@@ -351,7 +369,9 @@ func TestRestart(t *testing.T) {
 		actor := &testPostStop{}
 		assert.NotNil(t, actor)
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the actor ref
 		pid, err := newPID(ctx, actorPath, actor,
@@ -380,7 +400,9 @@ func TestSupervisorStrategy(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -415,7 +437,9 @@ func TestSupervisorStrategy(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx,
@@ -455,7 +479,9 @@ func TestSupervisorStrategy(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx,
@@ -496,7 +522,9 @@ func TestSupervisorStrategy(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx,
@@ -539,7 +567,9 @@ func TestSupervisorStrategy(t *testing.T) {
 
 		logger := log.DiscardLogger
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		// create the parent actor
 		parent, err := newPID(ctx,
 			actorPath,
@@ -581,7 +611,9 @@ func TestSupervisorStrategy(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx,
@@ -621,7 +653,8 @@ func TestSupervisorStrategy(t *testing.T) {
 
 		logger := log.DiscardLogger
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		// create the parent actor
 		parent, err := newPID(ctx,
 			actorPath,
@@ -667,7 +700,8 @@ func TestSupervisorStrategy(t *testing.T) {
 
 		logger := log.DiscardLogger
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the directive
 		restart := NewRestartDirective()
@@ -717,17 +751,17 @@ func TestMessaging(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
-
+		ports := dynaport.Get(1)
 		// create the actor path
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -763,17 +797,17 @@ func TestMessaging(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
-
+		ports := dynaport.Get(1)
 		// create the actor path
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -801,16 +835,17 @@ func TestMessaging(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
+		ports := dynaport.Get(1)
 
 		// create the actor path
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -838,17 +873,18 @@ func TestMessaging(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 			withAskTimeout(replyTimeout),
 		}
+		ports := dynaport.Get(1)
 
 		// create the actor path
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		actor2 := newTestActor()
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -917,7 +953,7 @@ func TestRemoting(t *testing.T) {
 	require.NoError(t, err)
 
 	// send the message to exchanger actor one using remote messaging
-	reply, err := actorRef2.RemoteAsk(ctx, addr1, new(testpb.TestReply))
+	reply, err := actorRef2.RemoteAsk(ctx, address.From(addr1), new(testpb.TestReply))
 	// perform some assertions
 	require.NoError(t, err)
 	require.NotNil(t, reply)
@@ -931,7 +967,7 @@ func TestRemoting(t *testing.T) {
 	assert.True(t, proto.Equal(expected, actual))
 
 	// send a message to stop the first exchange actor
-	err = actorRef2.RemoteTell(ctx, addr1, new(testpb.TestRemoteSend))
+	err = actorRef2.RemoteTell(ctx, address.From(addr1), new(testpb.TestRemoteSend))
 	require.NoError(t, err)
 
 	// stop the actor after some time
@@ -945,7 +981,8 @@ func TestRemoting(t *testing.T) {
 func TestActorHandle(t *testing.T) {
 	ctx := context.TODO()
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -970,7 +1007,8 @@ func TestActorHandle(t *testing.T) {
 func TestPIDActorSystem(t *testing.T) {
 	ctx := context.TODO()
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -993,7 +1031,8 @@ func TestSpawnChild(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -1033,7 +1072,8 @@ func TestSpawnChild(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -1069,7 +1109,8 @@ func TestSpawnChild(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -1096,7 +1137,8 @@ func TestSpawnChild(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -1122,7 +1164,8 @@ func TestSpawnChild(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		eventsStream := eventstream.New()
 
@@ -1164,7 +1207,7 @@ func TestSpawnChild(t *testing.T) {
 		require.Len(t, events, 1)
 
 		event := events[0]
-		assert.True(t, proto.Equal(parent.ActorPath().RemoteAddress(), event.GetParent()))
+		assert.True(t, proto.Equal(parent.Address().Address, event.GetParent()))
 
 		//stop the actor
 		err = parent.Shutdown(ctx)
@@ -1175,7 +1218,8 @@ func TestPoisonPill(t *testing.T) {
 	ctx := context.TODO()
 
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -1311,7 +1355,8 @@ func TestFailedPostStop(t *testing.T) {
 	ctx := context.TODO()
 
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -1332,7 +1377,8 @@ func TestShutdown(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -1366,7 +1412,8 @@ func TestBatchTell(t *testing.T) {
 
 		// create the actor path
 		actor := newTestActor()
-		actorPath := NewPath("testActor", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -1391,7 +1438,8 @@ func TestBatchTell(t *testing.T) {
 
 		// create the actor path
 		actor := newTestActor()
-		actorPath := NewPath("testActor", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -1416,7 +1464,8 @@ func TestBatchTell(t *testing.T) {
 
 		// create the actor path
 		actor := newTestActor()
-		actorPath := NewPath("testActor", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -1439,7 +1488,8 @@ func TestBatchAsk(t *testing.T) {
 
 		// create the actor path
 		actor := &exchanger{}
-		actorPath := NewPath("testActor", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -1468,7 +1518,8 @@ func TestBatchAsk(t *testing.T) {
 
 		// create the actor path
 		actor := &exchanger{}
-		actorPath := NewPath("testActor", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -1492,7 +1543,8 @@ func TestBatchAsk(t *testing.T) {
 
 		// create the actor path
 		actor := newTestActor()
-		actorPath := NewPath("testActor", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -1516,7 +1568,8 @@ func TestRegisterMetrics(t *testing.T) {
 	ctx := context.TODO()
 
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -1774,7 +1827,8 @@ func TestRemoteStop(t *testing.T) {
 func TestID(t *testing.T) {
 	ctx := context.TODO()
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -1874,7 +1928,7 @@ func TestRemoteSpawn(t *testing.T) {
 		require.NotNil(t, addr)
 
 		// send the message to exchanger actor one using remote messaging
-		reply, err := pid.RemoteAsk(ctx, addr, new(testpb.TestReply))
+		reply, err := pid.RemoteAsk(ctx, address.From(addr), new(testpb.TestReply))
 
 		require.NoError(t, err)
 		require.NotNil(t, reply)
@@ -1984,7 +2038,8 @@ func TestRemoteSpawn(t *testing.T) {
 func TestName(t *testing.T) {
 	ctx := context.TODO()
 	// create the actor path
-	actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+	ports := dynaport.Get(1)
+	actorPath := address.New("Test", "sys", "host", ports[0])
 
 	// create the actor ref
 	pid, err := newPID(
@@ -2019,17 +2074,18 @@ func TestPipeTo(t *testing.T) {
 			withPassivationDisabled(),
 			withCustomLogger(log.DiscardLogger),
 		}
+		ports := dynaport.Get(1)
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -2075,17 +2131,18 @@ func TestPipeTo(t *testing.T) {
 			withPassivationDisabled(),
 			withCustomLogger(log.DiscardLogger),
 		}
+		ports := dynaport.Get(1)
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -2112,17 +2169,18 @@ func TestPipeTo(t *testing.T) {
 			withPassivationDisabled(),
 			withCustomLogger(log.DiscardLogger),
 		}
+		ports := dynaport.Get(1)
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -2169,17 +2227,18 @@ func TestPipeTo(t *testing.T) {
 			withPassivationDisabled(),
 			withCustomLogger(log.DiscardLogger),
 		}
+		ports := dynaport.Get(1)
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -2206,17 +2265,18 @@ func TestPipeTo(t *testing.T) {
 			withPassivationDisabled(),
 			withCustomLogger(log.DiscardLogger),
 		}
+		ports := dynaport.Get(1)
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -2543,7 +2603,8 @@ func TestStopChild(t *testing.T) {
 		// create a test context
 		ctx := context.TODO()
 		// create the actor path
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
diff --git a/actors/receive_context_test.go b/actors/receive_context_test.go
index 2ff203c..783712d 100644
--- a/actors/receive_context_test.go
+++ b/actors/receive_context_test.go
@@ -35,6 +35,7 @@ import (
 	"github.com/travisjeffery/go-dynaport"
 	"google.golang.org/protobuf/proto"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/goaktpb"
 	"github.com/tochemey/goakt/v2/internal/eventstream"
 	"github.com/tochemey/goakt/v2/log"
@@ -53,7 +54,10 @@ func TestReceiveContext(t *testing.T) {
 
 		// create the actor path
 		actor := &userActor{}
-		actorPath := NewPath("User", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("User", "sys", "host", ports[0])
+
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -109,9 +113,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -126,7 +132,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -145,10 +151,10 @@ func TestReceiveContext(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
-
+		ports := dynaport.Get(1)
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -163,7 +169,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -184,10 +190,10 @@ func TestReceiveContext(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
-
+		ports := dynaport.Get(1)
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -202,7 +208,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -223,10 +229,10 @@ func TestReceiveContext(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
-
+		ports := dynaport.Get(1)
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -241,7 +247,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -287,7 +293,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -307,7 +314,7 @@ func TestReceiveContext(t *testing.T) {
 		// get the address of the exchanger actor one
 		addr1 := context.RemoteLookup(host, remotingPort, actorName2)
 		// send the message to t exchanger actor one using remote messaging
-		reply := context.RemoteAsk(addr1, new(testpb.TestReply))
+		reply := context.RemoteAsk(address.From(addr1), new(testpb.TestReply))
 		// perform some assertions
 		require.NotNil(t, reply)
 		require.True(t, reply.MessageIs(new(testpb.Reply)))
@@ -347,7 +354,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -365,12 +373,12 @@ func TestReceiveContext(t *testing.T) {
 			self:    pid1,
 		}
 
-		context.RemoteAsk(&goaktpb.Address{
+		context.RemoteAsk(address.From(&goaktpb.Address{
 			Host: "127.0.0.1",
 			Port: int32(remotingPort),
 			Name: actorName2,
 			Id:   "",
-		}, new(testpb.TestReply))
+		}), new(testpb.TestReply))
 		require.Error(t, context.getError())
 		pause(time.Second)
 
@@ -411,7 +419,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -432,7 +441,7 @@ func TestReceiveContext(t *testing.T) {
 		// get the address of the exchanger actor one
 		addr1 := context.RemoteLookup(host, remotingPort, actorName2)
 		// send the message to t exchanger actor one using remote messaging
-		context.RemoteTell(addr1, new(testpb.TestRemoteSend))
+		context.RemoteTell(address.From(addr1), new(testpb.TestRemoteSend))
 		require.NoError(t, context.getError())
 		pause(time.Second)
 
@@ -469,7 +478,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -488,12 +498,12 @@ func TestReceiveContext(t *testing.T) {
 		}
 
 		// send the message to the exchanger actor one using remote messaging
-		context.RemoteTell(&goaktpb.Address{
+		context.RemoteTell(address.From(&goaktpb.Address{
 			Host: "127.0.0.1",
 			Port: int32(remotingPort),
 			Name: actorName2,
 			Id:   "",
-		}, new(testpb.TestRemoteSend))
+		}), new(testpb.TestRemoteSend))
 		require.Error(t, context.getError())
 		pause(time.Second)
 
@@ -530,7 +540,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -584,7 +595,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -620,7 +632,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
@@ -639,7 +652,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With successful SpawnChild", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -667,7 +681,7 @@ func TestReceiveContext(t *testing.T) {
 
 		actual := receiveCtx.Child(name)
 		require.NotNil(t, actual)
-		assert.Equal(t, child.ActorPath().String(), actual.ActorPath().String())
+		assert.Equal(t, child.Address().String(), actual.Address().String())
 
 		t.Cleanup(func() {
 			receiveCtx.Shutdown()
@@ -675,7 +689,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With failed SpawnChild", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -704,7 +719,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With not found Child", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -741,7 +757,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With dead parent Child", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -778,7 +795,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With successful Stop", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -815,7 +833,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With child actor Stop freeing up parent link", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -856,7 +875,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With failed Stop: child not defined", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -886,7 +906,9 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With failed Stop: parent is dead", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		// create the actor path
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -923,7 +945,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With failed Stop: actor not found", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -944,7 +967,7 @@ func TestReceiveContext(t *testing.T) {
 		}
 
 		// create the child actor
-		childPath := NewPath("child", NewAddress("sys", "host", 1))
+		childPath := address.New("child", "sys", "host", ports[0])
 		child, err := newPID(ctx, childPath,
 			newTestSupervisor(),
 			withInitMaxRetries(1),
@@ -963,7 +986,8 @@ func TestReceiveContext(t *testing.T) {
 	})
 	t.Run("With Stop when child is already stopped", func(t *testing.T) {
 		ctx := context.TODO()
-		actorPath := NewPath("Parent", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath := address.New("Parent", "sys", "host", ports[0])
 
 		// create the parent actor
 		parent, err := newPID(ctx, actorPath,
@@ -1008,9 +1032,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &testPostStop{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -1034,16 +1060,18 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actorA
 		actorA := &exchanger{}
-		actorPath1 := NewPath("actorA", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("actorA", "sys", "host", ports[0])
 		pidA, err := newPID(ctx, actorPath1, actorA, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pidA)
 
 		// create actorC
 		actorC := &exchanger{}
-		actorPath3 := NewPath("actorC", NewAddress("sys", "host", 1))
+		actorPath3 := address.New("actorC", "sys", "host", ports[0])
 		pidC, err := newPID(ctx, actorPath3, actorC, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pidC)
@@ -1052,7 +1080,7 @@ func TestReceiveContext(t *testing.T) {
 		actorB := &forwarder{
 			actorRef: pidC,
 		}
-		actorPath2 := NewPath("actorB", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("actorB", "sys", "host", ports[0])
 		pidB, err := newPID(ctx, actorPath2, actorB, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pidB)
@@ -1089,9 +1117,11 @@ func TestReceiveContext(t *testing.T) {
 			withEventsStream(eventsStream),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
@@ -1155,16 +1185,18 @@ func TestReceiveContext(t *testing.T) {
 			withEventsStream(eventsStream),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 
 		send := new(testpb.TestSend)
@@ -1198,7 +1230,7 @@ func TestReceiveContext(t *testing.T) {
 		require.NoError(t, msg.UnmarshalTo(actual))
 		require.True(t, proto.Equal(send, actual))
 		require.Equal(t, deadletter.GetReason(), ErrUnhandled.Error())
-		assert.True(t, proto.Equal(deadletter.GetSender(), actorPath2.RemoteAddress()))
+		assert.True(t, proto.Equal(deadletter.GetSender(), actorPath2.Address))
 
 		assert.EqualValues(t, 1, len(consumer.Topics()))
 
@@ -1225,9 +1257,11 @@ func TestReceiveContext(t *testing.T) {
 			withEventsStream(eventsStream),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 
 		require.NoError(t, err)
@@ -1275,9 +1309,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -1292,7 +1328,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -1312,9 +1348,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -1329,7 +1367,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -1349,9 +1387,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -1366,7 +1406,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -1389,9 +1429,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -1406,7 +1448,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -1431,9 +1473,11 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
@@ -1448,7 +1492,7 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -1503,7 +1547,7 @@ func TestReceiveContext(t *testing.T) {
 		// get the address of the exchanger actor one
 		testerAddr := context.RemoteLookup(host, remotingPort, tester)
 		// send the message to t exchanger actor one using remote messaging
-		context.RemoteBatchTell(testerAddr, new(testpb.TestSend), new(testpb.TestSend), new(testpb.TestSend))
+		context.RemoteBatchTell(address.From(testerAddr), new(testpb.TestSend), new(testpb.TestSend), new(testpb.TestSend))
 		require.NoError(t, context.getError())
 		// wait for processing to complete on the actor side
 		pause(500 * time.Millisecond)
@@ -1556,7 +1600,7 @@ func TestReceiveContext(t *testing.T) {
 		// get the address of the exchanger actor one
 		testerAddr := context.RemoteLookup(host, remotingPort, tester)
 		// send the message to t exchanger actor one using remote messaging
-		replies := context.RemoteBatchAsk(testerAddr, new(testpb.TestReply), new(testpb.TestReply), new(testpb.TestReply))
+		replies := context.RemoteBatchAsk(address.From(testerAddr), new(testpb.TestReply), new(testpb.TestReply), new(testpb.TestReply))
 		require.NoError(t, context.getError())
 		require.Len(t, replies, 3)
 		pause(time.Second)
@@ -1593,8 +1637,9 @@ func TestReceiveContext(t *testing.T) {
 		actorName2 := "Exchange2"
 
 		// create actor1
+		ports := dynaport.Get(1)
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -1613,12 +1658,12 @@ func TestReceiveContext(t *testing.T) {
 		}
 
 		// send the message to the exchanger actor one using remote messaging
-		context.RemoteBatchTell(&goaktpb.Address{
+		context.RemoteBatchTell(address.From(&goaktpb.Address{
 			Host: "127.0.0.1",
 			Port: int32(remotingPort),
 			Name: actorName2,
 			Id:   "",
-		}, new(testpb.TestRemoteSend))
+		}), new(testpb.TestRemoteSend))
 		require.Error(t, context.getError())
 		pause(time.Second)
 
@@ -1654,8 +1699,9 @@ func TestReceiveContext(t *testing.T) {
 		actorName2 := "Exchange2"
 
 		// create actor1
+		ports := dynaport.Get(1)
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -1673,12 +1719,12 @@ func TestReceiveContext(t *testing.T) {
 			self:    pid1,
 		}
 
-		context.RemoteBatchAsk(&goaktpb.Address{
+		context.RemoteBatchAsk(address.From(&goaktpb.Address{
 			Host: "127.0.0.1",
 			Port: int32(remotingPort),
 			Name: actorName2,
 			Id:   "",
-		}, new(testpb.TestReply))
+		}), new(testpb.TestReply))
 		require.Error(t, context.getError())
 		pause(time.Second)
 
@@ -1714,8 +1760,9 @@ func TestReceiveContext(t *testing.T) {
 		actorName2 := "Exchange2"
 
 		// create actor1
+		ports := dynaport.Get(1)
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -1769,7 +1816,8 @@ func TestReceiveContext(t *testing.T) {
 
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		ports := dynaport.Get(1)
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx,
 			actorPath1,
 			actor1,
@@ -1807,16 +1855,17 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
@@ -1870,16 +1919,18 @@ func TestReceiveContext(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create actor1
 		actor1 := &exchanger{}
-		actorPath1 := NewPath("Exchange1", NewAddress("sys", "host", 1))
+		actorPath1 := address.New("Exchange1", "sys", "host", ports[0])
 		pid1, err := newPID(ctx, actorPath1, actor1, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid1)
 
 		// create actor2
 		actor2 := &exchanger{}
-		actorPath2 := NewPath("Exchange2", NewAddress("sys", "host", 1))
+		actorPath2 := address.New("Exchange2", "sys", "host", ports[0])
 		pid2, err := newPID(ctx, actorPath2, actor2, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid2)
diff --git a/actors/redistribution_test.go b/actors/redistribution_test.go
new file mode 100644
index 0000000..87e69f4
--- /dev/null
+++ b/actors/redistribution_test.go
@@ -0,0 +1,114 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2022-2024 Tochemey
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+package actors
+
+import (
+	"context"
+	"fmt"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"github.com/tochemey/goakt/v2/test/data/testpb"
+)
+
+func TestRedistribution(t *testing.T) {
+	t.Run("With successful actors redeployment", func(t *testing.T) {
+		// create a context
+		ctx := context.TODO()
+		// start the NATS server
+		srv := startNatsServer(t)
+
+		// create and start system cluster
+		node1, sd1 := startClusterSystem(t, "Node1", srv.Addr().String())
+		require.NotNil(t, node1)
+		require.NotNil(t, sd1)
+
+		// create and start system cluster
+		node2, sd2 := startClusterSystem(t, "Node2", srv.Addr().String())
+		require.NotNil(t, node2)
+		require.NotNil(t, sd2)
+
+		// create and start system cluster
+		node3, sd3 := startClusterSystem(t, "Node3", srv.Addr().String())
+		require.NotNil(t, node3)
+		require.NotNil(t, sd3)
+
+		// let us create 4 actors on each node
+		for j := 1; j <= 4; j++ {
+			actorName := fmt.Sprintf("Node1-Actor-%d", j)
+			pid, err := node1.Spawn(ctx, actorName, newTestActor())
+			require.NoError(t, err)
+			require.NotNil(t, pid)
+		}
+
+		pause(time.Second)
+
+		for j := 1; j <= 4; j++ {
+			actorName := fmt.Sprintf("Node2-Actor-%d", j)
+			pid, err := node2.Spawn(ctx, actorName, newTestActor())
+			require.NoError(t, err)
+			require.NotNil(t, pid)
+		}
+
+		pause(time.Second)
+
+		for j := 1; j <= 4; j++ {
+			actorName := fmt.Sprintf("Node3-Actor-%d", j)
+			pid, err := node3.Spawn(ctx, actorName, newTestActor())
+			require.NoError(t, err)
+			require.NotNil(t, pid)
+		}
+
+		pause(time.Second)
+
+		// take down node2
+		require.NoError(t, node2.Stop(ctx))
+		require.NoError(t, sd2.Close())
+
+		// Wait for cluster rebalancing
+		pause(time.Minute)
+
+		// let us access some of the node2 actors from node 1 and  node 3
+		actorName := "Node2-Actor-1"
+
+		sender, err := node1.LocalActor("Node1-Actor-1")
+		require.NoError(t, err)
+		require.NotNil(t, sender)
+
+		err = sender.SendAsync(ctx, actorName, new(testpb.TestSend))
+		require.NoError(t, err)
+
+		t.Cleanup(func() {
+			assert.NoError(t, node1.Stop(ctx))
+			assert.NoError(t, node3.Stop(ctx))
+			assert.NoError(t, sd1.Close())
+			assert.NoError(t, sd3.Close())
+			srv.Shutdown()
+		})
+	})
+}
diff --git a/actors/scheduler_test.go b/actors/scheduler_test.go
index 1afc0b8..e3f7628 100644
--- a/actors/scheduler_test.go
+++ b/actors/scheduler_test.go
@@ -33,6 +33,7 @@ import (
 	"github.com/stretchr/testify/require"
 	"github.com/travisjeffery/go-dynaport"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/log"
 	"github.com/tochemey/goakt/v2/test/data/testpb"
 )
@@ -85,8 +86,10 @@ func TestScheduler(t *testing.T) {
 	t.Run("With ScheduleOnce with scheduler not started", func(t *testing.T) {
 		ctx := context.TODO()
 		scheduler := newScheduler(log.DiscardLogger, time.Second)
+		ports := dynaport.Get(1)
+
 		// create the actor path
-		actorPath := NewPath("Test", NewAddress("sys", "host", 1))
+		actorPath := address.New("Test", "sys", "host", ports[0])
 
 		// create the actor ref
 		pid, err := newPID(
diff --git a/actors/stash_test.go b/actors/stash_test.go
index 3240326..db09cdb 100644
--- a/actors/stash_test.go
+++ b/actors/stash_test.go
@@ -31,7 +31,9 @@ import (
 
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
+	"github.com/travisjeffery/go-dynaport"
 
+	"github.com/tochemey/goakt/v2/address"
 	"github.com/tochemey/goakt/v2/log"
 	"github.com/tochemey/goakt/v2/test/data/testpb"
 )
@@ -46,9 +48,11 @@ func TestStash(t *testing.T) {
 			withStash(),
 		}
 
+		ports := dynaport.Get(1)
+
 		// create the actor path
 		actor := &stasher{}
-		actorPath := NewPath("stasher", NewAddress("sys", "host", 1))
+		actorPath := address.New("stasher", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -113,9 +117,10 @@ func TestStash(t *testing.T) {
 			withCustomLogger(log.DiscardLogger),
 		}
 
+		ports := dynaport.Get(1)
 		// create the actor path
 		actor := &stasher{}
-		actorPath := NewPath("stasher", NewAddress("sys", "host", 1))
+		actorPath := address.New("stasher", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
@@ -137,10 +142,10 @@ func TestStash(t *testing.T) {
 			withInitMaxRetries(1),
 			withCustomLogger(log.DiscardLogger),
 		}
-
+		ports := dynaport.Get(1)
 		// create the actor path
 		actor := &stasher{}
-		actorPath := NewPath("stasher", NewAddress("sys", "host", 1))
+		actorPath := address.New("stasher", "sys", "host", ports[0])
 		pid, err := newPID(ctx, actorPath, actor, opts...)
 		require.NoError(t, err)
 		require.NotNil(t, pid)
diff --git a/actors/address_test.go b/address/address_test.go
similarity index 51%
rename from actors/address_test.go
rename to address/address_test.go
index d903ba2..efdef1b 100644
--- a/actors/address_test.go
+++ b/address/address_test.go
@@ -22,93 +22,84 @@
  * SOFTWARE.
  */
 
-package actors
+package address
 
 import (
 	"testing"
 
-	"github.com/google/go-cmp/cmp"
 	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
+	"google.golang.org/protobuf/proto"
 )
 
 func TestAddress(t *testing.T) {
-	t.Run("With testCase1", func(t *testing.T) {
-		expected := "goakt://sys@host:1234"
-		addr := NewAddress("sys", "host", 1234)
-		assert.False(t, addr.IsLocal())
-		assert.True(t, addr.IsRemote())
+	t.Run("With happy path", func(t *testing.T) {
+		expected := "goakt://system@host:1234/name"
+		addr := New("name", "system", "host", 1234)
 		assert.Equal(t, "host:1234", addr.HostPort())
 		assert.Equal(t, "host", addr.Host())
+		assert.Equal(t, "name", addr.Name())
 		assert.EqualValues(t, 1234, addr.Port())
+		assert.NotEmpty(t, addr.ID())
+		assert.NotNil(t, addr.Parent())
+		assert.True(t, proto.Equal(addr.Parent(), NoSender))
 		assert.Equal(t, expected, addr.String())
 	})
-	t.Run("With testCase2", func(t *testing.T) {
-		expected := "goakt://sys@"
-		addr := NewAddress("sys", "", -1)
-		assert.False(t, addr.IsRemote())
-		assert.True(t, addr.IsLocal())
-		assert.Equal(t, expected, addr.String())
-		actual, err := addr.WithHost("localhost")
-		require.Error(t, err)
-		assert.EqualError(t, err, ErrLocalAddress.Error())
-		assert.Nil(t, actual)
-	})
-	t.Run("With testCase3", func(t *testing.T) {
-		expected := "goakt://sys@host:1234"
-		addr := NewAddress("sys", "host", 1234)
-		assert.False(t, addr.IsLocal())
-		assert.True(t, addr.IsRemote())
+
+	t.Run("With Host change", func(t *testing.T) {
+		expected := "goakt://system@host:1234/name"
+		addr := New("name", "system", "host", 1234)
 		assert.Equal(t, "host:1234", addr.HostPort())
 		assert.Equal(t, "host", addr.Host())
 		assert.EqualValues(t, 1234, addr.Port())
 		assert.Equal(t, expected, addr.String())
 
 		// change the host
-		actual, err := addr.WithHost("localhost")
-		require.NoError(t, err)
-		expected = "goakt://sys@localhost:1234"
-		assert.False(t, actual.IsLocal())
-		assert.True(t, actual.IsRemote())
+		actual := addr.WithHost("localhost")
+		expected = "goakt://system@localhost:1234/name"
 		assert.Equal(t, "localhost:1234", actual.HostPort())
 		assert.Equal(t, "localhost", actual.Host())
 		assert.EqualValues(t, 1234, actual.Port())
 		assert.Equal(t, expected, actual.String())
-
-		assert.False(t, cmp.Equal(addr, actual, cmp.AllowUnexported(Address{})))
-	})
-	t.Run("With port failure", func(t *testing.T) {
-		addr := NewAddress("sys", "", -1)
-		assert.False(t, addr.IsRemote())
-		assert.True(t, addr.IsLocal())
-		actual, err := addr.WithPort(3000)
-		assert.Error(t, err)
-		assert.EqualError(t, err, ErrLocalAddress.Error())
-		assert.Nil(t, actual)
 	})
-	t.Run("With port success", func(t *testing.T) {
-		addr := NewAddress("sys", "host", 1234)
-		expected := "goakt://sys@host:1234"
+
+	t.Run("With port change", func(t *testing.T) {
+		addr := New("name", "system", "host", 1234)
+		expected := "goakt://system@host:1234/name"
 		assert.Equal(t, expected, addr.String())
-		actual, err := addr.WithPort(3000)
-		assert.NoError(t, err)
+		actual := addr.WithPort(3000)
 		assert.NotNil(t, actual)
-		expected = "goakt://sys@host:3000"
+		expected = "goakt://system@host:3000/name"
 		assert.Equal(t, expected, actual.String())
 	})
-	t.Run("With address protocol", func(t *testing.T) {
-		addr := NewAddress("sys", "", -1)
-		assert.Equal(t, protocol, addr.Protocol())
-		addr = NewAddress("sys", "host", 1234)
-		assert.Equal(t, protocol, addr.Protocol())
-	})
-	t.Run("With Actor System", func(t *testing.T) {
-		addr := NewAddress("sys", "host", 1234)
-		expected := "goakt://sys@host:1234"
+
+	t.Run("With Actor System change", func(t *testing.T) {
+		addr := New("name", "system", "host", 1234)
+		expected := "goakt://system@host:1234/name"
 		assert.Equal(t, expected, addr.String())
 		actual := addr.WithSystem("MySyS")
 		assert.NotNil(t, actual)
-		expected = "goakt://MySyS@host:1234"
+		expected = "goakt://MySyS@host:1234/name"
 		assert.Equal(t, expected, actual.String())
 	})
+	t.Run("With Default", func(t *testing.T) {
+		addr := Default()
+		assert.NoError(t, addr.Validate())
+
+		addr.WithHost("localhost").WithPort(123).WithSystem("system").WithName("name")
+		assert.NoError(t, addr.Validate())
+		assert.Equal(t, "goakt://system@localhost:123/name", addr.String())
+	})
+	t.Run("With marshaling", func(t *testing.T) {
+		addr := New("name", "system", "host", 1234)
+
+		bytea, err := addr.MarshalBinary()
+		assert.NoError(t, err)
+		assert.NotNil(t, bytea)
+
+		actual := new(Address)
+		err = actual.UnmarshalBinary(bytea)
+		assert.NoError(t, err)
+
+		assert.True(t, actual.Equals(addr))
+	})
 }
diff --git a/client/client_test.go b/client/client_test.go
index 6b95d87..ebf9c5d 100644
--- a/client/client_test.go
+++ b/client/client_test.go
@@ -634,11 +634,11 @@ func startNode(t *testing.T, logger log.Logger, nodeName, serverAddr string) (sy
 	}
 
 	hostNode := discovery.Node{
-		Name:         nodeName,
-		Host:         host,
-		GossipPort:   gossipPort,
-		PeersPort:    peersPort,
-		RemotingPort: remotePort,
+		Name:          nodeName,
+		Host:          host,
+		DiscoveryPort: gossipPort,
+		PeersPort:     peersPort,
+		RemotingPort:  remotePort,
 	}
 
 	// create the instance of provider
@@ -649,14 +649,14 @@ func startNode(t *testing.T, logger log.Logger, nodeName, serverAddr string) (sy
 		WithKinds(new(testActor)).
 		WithDiscovery(natsProvider).
 		WithPeersPort(peersPort).
-		WithGossipPort(gossipPort).
+		WithDiscoveryPort(gossipPort).
 		WithReplicaCount(1).
 		WithMinimumPeersQuorum(1).
 		WithPartitionCount(10)
 
 	// create the actor system
 	system, err := actors.NewActorSystem(
-		applicationName,
+		actorSystemName,
 		actors.WithPassivationDisabled(),
 		actors.WithLogger(logger),
 		actors.WithReplyTimeout(time.Minute),
diff --git a/discovery/kubernetes/config_test.go b/discovery/kubernetes/config_test.go
index d156672..18ab7a3 100644
--- a/discovery/kubernetes/config_test.go
+++ b/discovery/kubernetes/config_test.go
@@ -33,23 +33,23 @@ import (
 func TestConfig(t *testing.T) {
 	t.Run("With valid configuration", func(t *testing.T) {
 		config := &Config{
-			Namespace:        "namespace",
-			ApplicationName:  "applicationName",
-			GossipPortName:   "gossipName",
-			RemotingPortName: "remotingName",
-			PeersPortName:    "peersPortName",
-			ActorSystemName:  "actorSys",
+			Namespace:         "namespace",
+			ApplicationName:   "applicationName",
+			DiscoveryPortName: "gossipName",
+			RemotingPortName:  "remotingName",
+			PeersPortName:     "peersPortName",
+			ActorSystemName:   "actorSys",
 		}
 		assert.NoError(t, config.Validate())
 	})
 	t.Run("With invalid configuration", func(t *testing.T) {
 		config := &Config{
-			Namespace:        "namespace",
-			ApplicationName:  "applicationName",
-			GossipPortName:   "",
-			RemotingPortName: "remotingName",
-			PeersPortName:    "peersPortName",
-			ActorSystemName:  "actorSys",
+			Namespace:         "namespace",
+			ApplicationName:   "applicationName",
+			DiscoveryPortName: "",
+			RemotingPortName:  "remotingName",
+			PeersPortName:     "peersPortName",
+			ActorSystemName:   "actorSys",
 		}
 		assert.Error(t, config.Validate())
 	})
diff --git a/discovery/kubernetes/discovery_test.go b/discovery/kubernetes/discovery_test.go
index 1304cab..00c987d 100644
--- a/discovery/kubernetes/discovery_test.go
+++ b/discovery/kubernetes/discovery_test.go
@@ -74,12 +74,12 @@ func TestDiscovery(t *testing.T) {
 		ts2 := time.Now()
 
 		config := &Config{
-			Namespace:        "test",
-			ActorSystemName:  "test",
-			ApplicationName:  "test",
-			GossipPortName:   gossipPortName,
-			RemotingPortName: remotingPortName,
-			PeersPortName:    peersPortName,
+			Namespace:         "test",
+			ActorSystemName:   "test",
+			ApplicationName:   "test",
+			DiscoveryPortName: gossipPortName,
+			RemotingPortName:  remotingPortName,
+			PeersPortName:     peersPortName,
 		}
 
 		// create some bunch of mock pods
@@ -210,12 +210,12 @@ func TestDiscovery(t *testing.T) {
 		actorSystemName := "AccountsSystem"
 
 		config := &Config{
-			Namespace:        namespace,
-			ActorSystemName:  actorSystemName,
-			ApplicationName:  applicationName,
-			GossipPortName:   gossipPortName,
-			RemotingPortName: remotingPortName,
-			PeersPortName:    peersPortName,
+			Namespace:         namespace,
+			ActorSystemName:   actorSystemName,
+			ApplicationName:   applicationName,
+			DiscoveryPortName: gossipPortName,
+			RemotingPortName:  remotingPortName,
+			PeersPortName:     peersPortName,
 		}
 
 		// create the instance of provider
diff --git a/discovery/nats/discovery_test.go b/discovery/nats/discovery_test.go
index 49dc6cc..801e7a6 100644
--- a/discovery/nats/discovery_test.go
+++ b/discovery/nats/discovery_test.go
@@ -85,11 +85,11 @@ func newPeer(t *testing.T, serverAddr string) *Discovery {
 	}
 
 	hostNode := discovery.Node{
-		Name:         host,
-		Host:         host,
-		GossipPort:   gossipPort,
-		PeersPort:    clusterPort,
-		RemotingPort: remotingPort,
+		Name:          host,
+		Host:          host,
+		DiscoveryPort: gossipPort,
+		PeersPort:     clusterPort,
+		RemotingPort:  remotingPort,
 	}
 
 	// create the instance of provider
@@ -129,11 +129,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		// create the instance of provider
@@ -173,11 +173,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 		// create the instance of provider
 		provider := NewDiscovery(config, &hostNode)
@@ -212,11 +212,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		// create the instance of provider
@@ -257,11 +257,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		// create the instance of provider
@@ -297,11 +297,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		// create the instance of provider
@@ -339,11 +339,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		// create the instance of provider
@@ -382,7 +382,7 @@ func TestDiscovery(t *testing.T) {
 		require.NoError(t, err)
 		require.NotEmpty(t, peers)
 		require.Len(t, peers, 1)
-		discoveredNodeAddr := client2.hostNode.GossipAddress()
+		discoveredNodeAddr := client2.hostNode.DiscoveryAddress()
 		require.Equal(t, peers[0], discoveredNodeAddr)
 
 		// discover more peers from client 2
@@ -390,7 +390,7 @@ func TestDiscovery(t *testing.T) {
 		require.NoError(t, err)
 		require.NotEmpty(t, peers)
 		require.Len(t, peers, 1)
-		discoveredNodeAddr = client1.hostNode.GossipAddress()
+		discoveredNodeAddr = client1.hostNode.DiscoveryAddress()
 		require.Equal(t, peers[0], discoveredNodeAddr)
 
 		// de-register client 2 but it can see client1
@@ -398,7 +398,7 @@ func TestDiscovery(t *testing.T) {
 		peers, err = client2.DiscoverPeers()
 		require.NoError(t, err)
 		require.NotEmpty(t, peers)
-		discoveredNodeAddr = client1.hostNode.GossipAddress()
+		discoveredNodeAddr = client1.hostNode.DiscoveryAddress()
 		require.Equal(t, peers[0], discoveredNodeAddr)
 
 		// client-1 cannot see the deregistered client
@@ -440,11 +440,11 @@ func TestDiscovery(t *testing.T) {
 		}
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		provider := NewDiscovery(config, &hostNode)
diff --git a/internal/cluster/codec_test.go b/internal/cluster/codec_test.go
index fd8cbc7..cfb2050 100644
--- a/internal/cluster/codec_test.go
+++ b/internal/cluster/codec_test.go
@@ -39,8 +39,7 @@ import (
 func TestCodec(t *testing.T) {
 	t.Run("With happy path", func(t *testing.T) {
 		// create an instance of wire actor
-		actor := &internalpb.WireActor{
-			ActorName: "account-1",
+		actor := &internalpb.ActorRef{
 			ActorAddress: &goaktpb.Address{
 				Host: "127.0.0.1",
 				Port: 2345,
diff --git a/internal/cluster/engine_test.go b/internal/cluster/engine_test.go
index 738a684..44bc172 100644
--- a/internal/cluster/engine_test.go
+++ b/internal/cluster/engine_test.go
@@ -78,11 +78,11 @@ func TestSingleNode(t *testing.T) {
 		host := "127.0.0.1"
 
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		logger := log.New(log.ErrorLevel, os.Stdout)
@@ -133,11 +133,11 @@ func TestSingleNode(t *testing.T) {
 		// create a Node startNode
 		host := "127.0.0.1"
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		cluster, err := NewEngine("test", provider, &hostNode)
@@ -150,7 +150,7 @@ func TestSingleNode(t *testing.T) {
 
 		// create an actor
 		actorName := uuid.NewString()
-		actor := &internalpb.WireActor{ActorName: actorName}
+		actor := &internalpb.ActorRef{ActorAddress: &goaktpb.Address{Name: actorName}}
 
 		// replicate the actor in the Node
 		err = cluster.PutActor(ctx, actor)
@@ -203,11 +203,11 @@ func TestSingleNode(t *testing.T) {
 		// create a Node startNode
 		host := "127.0.0.1"
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    clusterPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     clusterPort,
+			RemotingPort:  remotingPort,
 		}
 
 		cluster, err := NewEngine("test", provider, &hostNode)
@@ -270,11 +270,11 @@ func TestSingleNode(t *testing.T) {
 		// create a Node startNode
 		host := "127.0.0.1"
 		hostNode := discovery.Node{
-			Name:         host,
-			Host:         host,
-			GossipPort:   gossipPort,
-			PeersPort:    peersPort,
-			RemotingPort: remotingPort,
+			Name:          host,
+			Host:          host,
+			DiscoveryPort: gossipPort,
+			PeersPort:     peersPort,
+			RemotingPort:  remotingPort,
 		}
 
 		logger := log.New(log.WarningLevel, os.Stdout)
@@ -288,7 +288,7 @@ func TestSingleNode(t *testing.T) {
 
 		// create an actor
 		actorName := uuid.NewString()
-		actor := &internalpb.WireActor{ActorName: actorName}
+		actor := &internalpb.ActorRef{ActorAddress: &goaktpb.Address{Name: actorName}}
 		// replicate the actor in the Node
 		err = cluster.PutActor(ctx, actor)
 		require.NoError(t, err)
@@ -454,11 +454,11 @@ func startEngine(t *testing.T, nodeName, serverAddr string) (*Engine, discovery.
 	}
 
 	hostNode := discovery.Node{
-		Name:         host,
-		Host:         host,
-		GossipPort:   gossipPort,
-		PeersPort:    clusterPort,
-		RemotingPort: remotingPort,
+		Name:          host,
+		Host:          host,
+		DiscoveryPort: gossipPort,
+		PeersPort:     clusterPort,
+		RemotingPort:  remotingPort,
 	}
 
 	// create the instance of provider
diff --git a/internal/validation/tcp_address_test.go b/internal/validation/tcp_address_test.go
index 974b99c..b93121f 100644
--- a/internal/validation/tcp_address_test.go
+++ b/internal/validation/tcp_address_test.go
@@ -43,9 +43,9 @@ func TestTCPAddressValidator(t *testing.T) {
 		addr := "127.0.0.1:655387"
 		assert.Error(t, NewTCPAddressValidator(addr).Validate())
 	})
-	t.Run("With invalid port number: case 3", func(t *testing.T) {
+	t.Run("With  zero port number: case 3", func(t *testing.T) {
 		addr := "127.0.0.1:0"
-		assert.Error(t, NewTCPAddressValidator(addr).Validate())
+		assert.NoError(t, NewTCPAddressValidator(addr).Validate())
 	})
 	t.Run("With invalid host", func(t *testing.T) {
 		addr := ":3222"
diff --git a/telemetry/option_test.go b/telemetry/option_test.go
index 645021f..5ee0031 100644
--- a/telemetry/option_test.go
+++ b/telemetry/option_test.go
@@ -44,12 +44,12 @@ func TestOptions(t *testing.T) {
 		{
 			name:           "WithTracerProvider",
 			option:         WithTracerProvider(tracerProvider),
-			expectedConfig: Telemetry{TracerProvider: tracerProvider},
+			expectedConfig: Telemetry{tracerProvider: tracerProvider},
 		},
 		{
 			name:           "WithMeterProvider",
 			option:         WithMeterProvider(meterProvider),
-			expectedConfig: Telemetry{MeterProvider: meterProvider},
+			expectedConfig: Telemetry{meterProvider: meterProvider},
 		},
 	}
 	for _, tc := range testCases {
diff --git a/actors/path_test.go b/telemetry/telemetry_test.go
similarity index 51%
rename from actors/path_test.go
rename to telemetry/telemetry_test.go
index d263ca0..cb439e6 100644
--- a/actors/path_test.go
+++ b/telemetry/telemetry_test.go
@@ -22,56 +22,32 @@
  * SOFTWARE.
  */
 
-package actors
+package telemetry
 
 import (
 	"testing"
 
-	"github.com/google/go-cmp/cmp"
-	"github.com/google/go-cmp/cmp/cmpopts"
 	"github.com/stretchr/testify/assert"
-	"github.com/stretchr/testify/require"
-	"google.golang.org/protobuf/encoding/prototext"
-
-	"github.com/tochemey/goakt/v2/goaktpb"
+	"go.opentelemetry.io/otel"
+	"go.opentelemetry.io/otel/metric"
+	"go.opentelemetry.io/otel/trace"
 )
 
-func TestPath(t *testing.T) {
-	name := "testActor"
-	addr := &Address{
-		host:     "localhost",
-		port:     888,
-		system:   "Sys",
-		protocol: protocol,
-	}
-
-	path := NewPath(name, addr)
-	assert.NotNil(t, path)
-	assert.IsType(t, new(Path), path)
-
-	// these are just routine assertions
-	require.Equal(t, name, path.Name())
-	require.Equal(t, "goakt://Sys@localhost:888/testActor", path.String())
-	remoteAddr := &goaktpb.Address{
-		Host: "localhost",
-		Port: 888,
-		Name: name,
-		Id:   path.ID().String(),
-	}
-
-	pathRemoteAddr := path.RemoteAddress()
-	assert.Equal(t, prototext.Format(remoteAddr), prototext.Format(pathRemoteAddr))
-
-	parent := NewPath("parent", &Address{
-		host:     "localhost",
-		port:     887,
-		system:   "Sys",
-		protocol: protocol,
-	})
-
-	newPath := path.WithParent(parent)
-	assert.True(t, cmp.Equal(parent, newPath.Parent(), cmpopts.IgnoreUnexported(Path{})))
-
-	pathCopy := path
-	require.True(t, path.Equals(pathCopy))
+func TestTelemetry(t *testing.T) {
+	tel := New()
+	assert.NotNil(t, tel)
+	globalTracer := otel.GetTracerProvider()
+	globalMeterProvider := otel.GetMeterProvider()
+
+	actual := tel.TraceProvider()
+	assert.NotNil(t, actual)
+	assert.Equal(t, globalTracer, actual)
+	assert.Equal(t, globalTracer.Tracer(instrumentationName,
+		trace.WithInstrumentationVersion(Version())), tel.Tracer())
+
+	actualmp := tel.MeterProvider()
+	assert.NotNil(t, actualmp)
+	assert.Equal(t, globalMeterProvider, actualmp)
+	assert.Equal(t, globalMeterProvider.Meter(instrumentationName,
+		metric.WithInstrumentationVersion(Version())), tel.Meter())
 }
diff --git a/testkit/probe_test.go b/testkit/probe_test.go
index d36f906..249a9fd 100644
--- a/testkit/probe_test.go
+++ b/testkit/probe_test.go
@@ -81,7 +81,7 @@ func TestTestProbe(t *testing.T) {
 
 		actual := probe.ExpectMessage(msg)
 		require.Equal(t, prototext.Format(msg), prototext.Format(actual))
-		require.Equal(t, pinger.ActorPath().String(), probe.Sender().ActorPath().String())
+		require.Equal(t, pinger.Address().String(), probe.Sender().Address().String())
 		probe.ExpectNoMessage()
 
 		t.Cleanup(func() {