From 17a406c880156895fb731f881119aea7fbf25d86 Mon Sep 17 00:00:00 2001 From: Richard Carillo Date: Thu, 7 May 2026 09:52:56 -0400 Subject: [PATCH 1/4] feat(service/backend): add support for the 'max-use' and 'max-lifetime' flags --- pkg/commands/service/backend/backend_test.go | 6 ++++++ pkg/commands/service/backend/create.go | 10 ++++++++++ pkg/commands/service/backend/describe.go | 2 ++ pkg/commands/service/backend/update.go | 11 +++++++++++ pkg/text/backend.go | 2 ++ 5 files changed, 31 insertions(+) diff --git a/pkg/commands/service/backend/backend_test.go b/pkg/commands/service/backend/backend_test.go index b15b7a4b7..059456907 100644 --- a/pkg/commands/service/backend/backend_test.go +++ b/pkg/commands/service/backend/backend_test.go @@ -590,6 +590,8 @@ var listBackendsVerboseOutput = strings.Join([]string{ " Override host: ", " Connect timeout: 0", " Max connections: 0", + " Max connection use: 0", + " Max connection lifetime: 0", " First byte timeout: 0", " Between bytes timeout: 0", " Auto loadbalance: false", @@ -619,6 +621,8 @@ var listBackendsVerboseOutput = strings.Join([]string{ " Override host: ", " Connect timeout: 0", " Max connections: 0", + " Max connection use: 0", + " Max connection lifetime: 0", " First byte timeout: 0", " Between bytes timeout: 0", " Auto loadbalance: false", @@ -668,6 +672,8 @@ var describeBackendOutput = strings.Join([]string{ "Override host: ", "Connect timeout: 0", "Max connections: 0", + "Max connection use: 0", + "Max connection lifetime: 0", "First byte timeout: 0", "Between bytes timeout: 0", "Auto loadbalance: false", diff --git a/pkg/commands/service/backend/create.go b/pkg/commands/service/backend/create.go index 4e4a64497..0ac1e85b5 100644 --- a/pkg/commands/service/backend/create.go +++ b/pkg/commands/service/backend/create.go @@ -32,6 +32,8 @@ type CreateCommand struct { firstByteTimeout argparser.OptionalInt healthCheck argparser.OptionalString maxConn argparser.OptionalInt + MaxUse argparser.OptionalInt + MaxLifetime argparser.OptionalInt maxTLSVersion argparser.OptionalString minTLSVersion argparser.OptionalString name argparser.OptionalString @@ -89,6 +91,8 @@ func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateComman c.CmdClause.Flag("first-byte-timeout", "How long to wait for the first bytes in milliseconds").Action(c.firstByteTimeout.Set).IntVar(&c.firstByteTimeout.Value) c.CmdClause.Flag("healthcheck", "The name of the healthcheck to use with this backend").Action(c.healthCheck.Set).StringVar(&c.healthCheck.Value) c.CmdClause.Flag("max-conn", "Maximum number of connections").Action(c.maxConn.Set).IntVar(&c.maxConn.Value) + c.CmdClause.Flag("max-use", "Maximum number of times an HTTP keepalive connection can be used").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) + c.CmdClause.Flag("max-lifetime", "Upper bound in milliseconds for how long an HTTP keepalive connection can be open before it is no longer used").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) c.CmdClause.Flag("max-tls-version", "Maximum allowed TLS version on SSL connections to this backend").Action(c.maxTLSVersion.Set).StringVar(&c.maxTLSVersion.Value) c.CmdClause.Flag("min-tls-version", "Minimum allowed TLS version on SSL connections to this backend").Action(c.minTLSVersion.Set).StringVar(&c.minTLSVersion.Value) c.CmdClause.Flag("name", "Backend name").Short('n').Action(c.name.Set).StringVar(&c.name.Value) @@ -180,6 +184,12 @@ func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error { if c.maxConn.WasSet { input.MaxConn = &c.maxConn.Value } + if c.MaxUse.WasSet { + input.MaxUse = &c.MaxUse.Value + } + if c.MaxLifetime.WasSet { + input.MaxLifetime = &c.MaxLifetime.Value + } if c.maxTLSVersion.WasSet { input.MaxTLSVersion = &c.maxTLSVersion.Value } diff --git a/pkg/commands/service/backend/describe.go b/pkg/commands/service/backend/describe.go index 9c2c37247..548479a41 100644 --- a/pkg/commands/service/backend/describe.go +++ b/pkg/commands/service/backend/describe.go @@ -112,6 +112,8 @@ func (c *DescribeCommand) print(out io.Writer, b *fastly.Backend) error { fmt.Fprintf(out, "Override host: %v\n", fastly.ToValue(b.OverrideHost)) fmt.Fprintf(out, "Connect timeout: %v\n", fastly.ToValue(b.ConnectTimeout)) fmt.Fprintf(out, "Max connections: %v\n", fastly.ToValue(b.MaxConn)) + fmt.Fprintf(out, "Max connection use: %v\n", fastly.ToValue(b.MaxUse)) + fmt.Fprintf(out, "Max connection lifetime: %v\n", fastly.ToValue(b.MaxLifetime)) fmt.Fprintf(out, "First byte timeout: %v\n", fastly.ToValue(b.FirstByteTimeout)) fmt.Fprintf(out, "Between bytes timeout: %v\n", fastly.ToValue(b.BetweenBytesTimeout)) fmt.Fprintf(out, "Auto loadbalance: %v\n", fastly.ToValue(b.AutoLoadbalance)) diff --git a/pkg/commands/service/backend/update.go b/pkg/commands/service/backend/update.go index e0ac49c36..6256ffb20 100644 --- a/pkg/commands/service/backend/update.go +++ b/pkg/commands/service/backend/update.go @@ -31,6 +31,8 @@ type UpdateCommand struct { HealthCheck argparser.OptionalString Hostname argparser.OptionalString MaxConn argparser.OptionalInt + MaxUse argparser.OptionalInt + MaxLifetime argparser.OptionalInt MaxTLSVersion argparser.OptionalString MinTLSVersion argparser.OptionalString NewName argparser.OptionalString @@ -87,6 +89,8 @@ func NewUpdateCommand(parent argparser.Registerer, g *global.Data) *UpdateComman c.CmdClause.Flag("first-byte-timeout", "How long to wait for the first bytes in milliseconds").Action(c.FirstByteTimeout.Set).IntVar(&c.FirstByteTimeout.Value) c.CmdClause.Flag("healthcheck", "The name of the healthcheck to use with this backend").Action(c.HealthCheck.Set).StringVar(&c.HealthCheck.Value) c.CmdClause.Flag("max-conn", "Maximum number of connections").Action(c.MaxConn.Set).IntVar(&c.MaxConn.Value) + c.CmdClause.Flag("max-use", "Maximum number of times an HTTP keepalive connection can be used").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) + c.CmdClause.Flag("max-lifetime", "Upper bound in milliseconds for how long an HTTP keepalive connection can be open before it is no longer used").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) c.CmdClause.Flag("max-tls-version", "Maximum allowed TLS version on SSL connections to this backend").Action(c.MaxTLSVersion.Set).StringVar(&c.MaxTLSVersion.Value) c.CmdClause.Flag("min-tls-version", "Minimum allowed TLS version on SSL connections to this backend").Action(c.MinTLSVersion.Set).StringVar(&c.MinTLSVersion.Value) c.CmdClause.Flag("new-name", "New backend name").Action(c.NewName.Set).StringVar(&c.NewName.Value) @@ -189,6 +193,13 @@ func (c *UpdateCommand) Exec(_ io.Reader, out io.Writer) error { input.MaxConn = &c.MaxConn.Value } + if c.MaxUse.WasSet { + input.MaxUse = &c.MaxUse.Value + } + if c.MaxLifetime.WasSet { + input.MaxLifetime = &c.MaxLifetime.Value + } + if c.FirstByteTimeout.WasSet { input.FirstByteTimeout = &c.FirstByteTimeout.Value } diff --git a/pkg/text/backend.go b/pkg/text/backend.go index d0f79b800..ffd5360eb 100644 --- a/pkg/text/backend.go +++ b/pkg/text/backend.go @@ -22,6 +22,8 @@ func PrintBackend(out io.Writer, prefix string, b *fastly.Backend) { fmt.Fprintf(out, "Override host: %v\n", fastly.ToValue(b.OverrideHost)) fmt.Fprintf(out, "Connect timeout: %v\n", fastly.ToValue(b.ConnectTimeout)) fmt.Fprintf(out, "Max connections: %v\n", fastly.ToValue(b.MaxConn)) + fmt.Fprintf(out, "Max connection use: %v\n", fastly.ToValue(b.MaxUse)) + fmt.Fprintf(out, "Max connection lifetime: %v\n", fastly.ToValue(b.MaxLifetime)) fmt.Fprintf(out, "First byte timeout: %v\n", fastly.ToValue(b.FirstByteTimeout)) fmt.Fprintf(out, "Between bytes timeout: %v\n", fastly.ToValue(b.BetweenBytesTimeout)) fmt.Fprintf(out, "Auto loadbalance: %v\n", fastly.ToValue(b.AutoLoadbalance)) From 4166a0f91ca0f419ca0a2a11f01b642d90045dbf Mon Sep 17 00:00:00 2001 From: Richard Carillo Date: Thu, 7 May 2026 09:58:27 -0400 Subject: [PATCH 2/4] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 061cbdc06..2dc73a58d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ ### Enhancements: +- feat(service/backend): add support for the `max_use` and `max_lifetime` parameters ([#1779](https://github.com/fastly/cli/pull/1779)) + ### Dependencies: - build(deps): `golang.org/x/term` from 0.41.0 to 0.42.0 ([#1726](https://github.com/fastly/cli/pull/1726)) - build(deps): `golang.org/x/crypto` from 0.49.0 to 0.50.0 ([#1726](https://github.com/fastly/cli/pull/1726)) From dfbba9a197d37087293fdfafc694f5026f3b706f Mon Sep 17 00:00:00 2001 From: Richard Carillo Date: Thu, 7 May 2026 10:11:19 -0400 Subject: [PATCH 3/4] (service/backend): updated flag descriptions to match live docs --- pkg/commands/service/backend/create.go | 4 ++-- pkg/commands/service/backend/update.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/commands/service/backend/create.go b/pkg/commands/service/backend/create.go index 0ac1e85b5..2edf4b380 100644 --- a/pkg/commands/service/backend/create.go +++ b/pkg/commands/service/backend/create.go @@ -91,8 +91,8 @@ func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateComman c.CmdClause.Flag("first-byte-timeout", "How long to wait for the first bytes in milliseconds").Action(c.firstByteTimeout.Set).IntVar(&c.firstByteTimeout.Value) c.CmdClause.Flag("healthcheck", "The name of the healthcheck to use with this backend").Action(c.healthCheck.Set).StringVar(&c.healthCheck.Value) c.CmdClause.Flag("max-conn", "Maximum number of connections").Action(c.maxConn.Set).IntVar(&c.maxConn.Value) - c.CmdClause.Flag("max-use", "Maximum number of times an HTTP keepalive connection can be used").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) - c.CmdClause.Flag("max-lifetime", "Upper bound in milliseconds for how long an HTTP keepalive connection can be open before it is no longer used").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) + c.CmdClause.Flag("max-use", "Maximum number of requests allowed over a single, pooled HTTP keepalive connection to this backend; 0 is treated as unlimited.").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) + c.CmdClause.Flag("max-lifetime", "Maximum time from creation (in milliseconds) that a pooled HTTP keepalive connection will be eligible for reuse; 0 is treated as unlimited.").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) c.CmdClause.Flag("max-tls-version", "Maximum allowed TLS version on SSL connections to this backend").Action(c.maxTLSVersion.Set).StringVar(&c.maxTLSVersion.Value) c.CmdClause.Flag("min-tls-version", "Minimum allowed TLS version on SSL connections to this backend").Action(c.minTLSVersion.Set).StringVar(&c.minTLSVersion.Value) c.CmdClause.Flag("name", "Backend name").Short('n').Action(c.name.Set).StringVar(&c.name.Value) diff --git a/pkg/commands/service/backend/update.go b/pkg/commands/service/backend/update.go index 6256ffb20..22b8b97d7 100644 --- a/pkg/commands/service/backend/update.go +++ b/pkg/commands/service/backend/update.go @@ -89,8 +89,8 @@ func NewUpdateCommand(parent argparser.Registerer, g *global.Data) *UpdateComman c.CmdClause.Flag("first-byte-timeout", "How long to wait for the first bytes in milliseconds").Action(c.FirstByteTimeout.Set).IntVar(&c.FirstByteTimeout.Value) c.CmdClause.Flag("healthcheck", "The name of the healthcheck to use with this backend").Action(c.HealthCheck.Set).StringVar(&c.HealthCheck.Value) c.CmdClause.Flag("max-conn", "Maximum number of connections").Action(c.MaxConn.Set).IntVar(&c.MaxConn.Value) - c.CmdClause.Flag("max-use", "Maximum number of times an HTTP keepalive connection can be used").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) - c.CmdClause.Flag("max-lifetime", "Upper bound in milliseconds for how long an HTTP keepalive connection can be open before it is no longer used").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) + c.CmdClause.Flag("max-use", "Maximum number of requests allowed over a single, pooled HTTP keepalive connection to this backend; 0 is treated as unlimited.").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) + c.CmdClause.Flag("max-lifetime", "Maximum time from creation (in milliseconds) that a pooled HTTP keepalive connection will be eligible for reuse; 0 is treated as unlimited.").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) c.CmdClause.Flag("max-tls-version", "Maximum allowed TLS version on SSL connections to this backend").Action(c.MaxTLSVersion.Set).StringVar(&c.MaxTLSVersion.Value) c.CmdClause.Flag("min-tls-version", "Minimum allowed TLS version on SSL connections to this backend").Action(c.MinTLSVersion.Set).StringVar(&c.MinTLSVersion.Value) c.CmdClause.Flag("new-name", "New backend name").Action(c.NewName.Set).StringVar(&c.NewName.Value) From c415db1934c072d1079632bdcafdf2f5f0e7339e Mon Sep 17 00:00:00 2001 From: Richard Carillo Date: Thu, 7 May 2026 10:33:14 -0400 Subject: [PATCH 4/4] (service/backend): remove export of new flags in Create --- pkg/commands/service/backend/create.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pkg/commands/service/backend/create.go b/pkg/commands/service/backend/create.go index 2edf4b380..8f2a5389c 100644 --- a/pkg/commands/service/backend/create.go +++ b/pkg/commands/service/backend/create.go @@ -32,8 +32,8 @@ type CreateCommand struct { firstByteTimeout argparser.OptionalInt healthCheck argparser.OptionalString maxConn argparser.OptionalInt - MaxUse argparser.OptionalInt - MaxLifetime argparser.OptionalInt + maxUse argparser.OptionalInt + maxLifetime argparser.OptionalInt maxTLSVersion argparser.OptionalString minTLSVersion argparser.OptionalString name argparser.OptionalString @@ -91,8 +91,8 @@ func NewCreateCommand(parent argparser.Registerer, g *global.Data) *CreateComman c.CmdClause.Flag("first-byte-timeout", "How long to wait for the first bytes in milliseconds").Action(c.firstByteTimeout.Set).IntVar(&c.firstByteTimeout.Value) c.CmdClause.Flag("healthcheck", "The name of the healthcheck to use with this backend").Action(c.healthCheck.Set).StringVar(&c.healthCheck.Value) c.CmdClause.Flag("max-conn", "Maximum number of connections").Action(c.maxConn.Set).IntVar(&c.maxConn.Value) - c.CmdClause.Flag("max-use", "Maximum number of requests allowed over a single, pooled HTTP keepalive connection to this backend; 0 is treated as unlimited.").Action(c.MaxUse.Set).IntVar(&c.MaxUse.Value) - c.CmdClause.Flag("max-lifetime", "Maximum time from creation (in milliseconds) that a pooled HTTP keepalive connection will be eligible for reuse; 0 is treated as unlimited.").Action(c.MaxLifetime.Set).IntVar(&c.MaxLifetime.Value) + c.CmdClause.Flag("max-use", "Maximum number of requests allowed over a single, pooled HTTP keepalive connection to this backend; 0 is treated as unlimited.").Action(c.maxUse.Set).IntVar(&c.maxUse.Value) + c.CmdClause.Flag("max-lifetime", "Maximum time from creation (in milliseconds) that a pooled HTTP keepalive connection will be eligible for reuse; 0 is treated as unlimited.").Action(c.maxLifetime.Set).IntVar(&c.maxLifetime.Value) c.CmdClause.Flag("max-tls-version", "Maximum allowed TLS version on SSL connections to this backend").Action(c.maxTLSVersion.Set).StringVar(&c.maxTLSVersion.Value) c.CmdClause.Flag("min-tls-version", "Minimum allowed TLS version on SSL connections to this backend").Action(c.minTLSVersion.Set).StringVar(&c.minTLSVersion.Value) c.CmdClause.Flag("name", "Backend name").Short('n').Action(c.name.Set).StringVar(&c.name.Value) @@ -184,11 +184,11 @@ func (c *CreateCommand) Exec(_ io.Reader, out io.Writer) error { if c.maxConn.WasSet { input.MaxConn = &c.maxConn.Value } - if c.MaxUse.WasSet { - input.MaxUse = &c.MaxUse.Value + if c.maxUse.WasSet { + input.MaxUse = &c.maxUse.Value } - if c.MaxLifetime.WasSet { - input.MaxLifetime = &c.MaxLifetime.Value + if c.maxLifetime.WasSet { + input.MaxLifetime = &c.maxLifetime.Value } if c.maxTLSVersion.WasSet { input.MaxTLSVersion = &c.maxTLSVersion.Value