Railway's August 14, 2026 changelog entry looks small: Access Groups, better template editing, and Railway Agent Connectors. Under the hood it is a permissions primitive — the same group-scoped RBAC boundary platform teams have been drawing in Kubernetes for a decade, only this time rented behind a SaaS UI instead of owned as YAML.
If you run apps on Railway, the feature decides who can see which project. If you run your own fleet under Cluster API, the same decision lives one layer lower: in rbac.authorization.k8s.io.
Here is the mapping, up front, because this is the post:
| Railway (rented) | Kubernetes (owned) | What it controls |
|---|---|---|
| Access Group (Workspace → People → Groups) | Group subject (kind: Group) via OIDC claim | Who belongs together |
| Project Role assigned to the group | Role / ClusterRole (rules: [...]) | What the group can do |
| Projects attached to the group | RoleBindings in each namespace | Where the group can do it |
| Enforcement toggle (Workspace → People → Security, with preview of lost access) | RBAC deny by default + admission / OPA / Kyverno | How the boundary is enforced |
| Workspace admin (sees every project regardless) | ClusterRoleBinding → cluster-admin | Break-glass / platform owner |
| Direct project grant or creator | User / ServiceAccount subject on a RoleBinding | Exceptions outside the group |
The rest of this post puts real semantics behind each row — what Railway actually shipped, what the equivalent looks like as YAML you commit, and where owning the control plane stops being a skin change and starts being a different boundary.
What Railway actually shipped (August 14, with context)
Access Groups entered beta on August 14, 2026, for Enterprise workspaces on committed-spend plans. The mental model, from Railway's changelog:
- Admins group people, assign a project role, and attach that group to any set of projects at Workspace settings → People → Groups.
- Audit effective access at Project settings → Members.
- Groups can be configured before enforcement; enforcement itself is flipped at Workspace settings → People → Security. Railway shows a preview of who would lose access and which projects would be left without a non-admin member before you commit.
- Once enforced, non-admins only see a project if they have access via a group, a direct grant, or because they created it. Workspace admins retain access to every project regardless.
Two details matter for the comparison. First, the pre-enforcement preview exists because PaaS RBAC is additive and the blast radius of a misclick is a team losing deploy access — Railway has to simulate the deny before it applies it. Second, the creator bypass (you always see what you created) has no direct Kubernetes analog; Kubernetes has no object-ownership fallback, only bindings.
Railway Agent Connectors, also beta and behind a Feature Flag, sit on a different axis. Enabled at Workspace settings → Agents, they let an agent chat attach Notion (search pages and databases), Linear (issues, projects, cycles), Sentry (issues and stack traces), or a custom remote MCP server via OAuth. Each connector is owned by its creator, usable only in that person's agent runs, with private credentials, and attached per-chat through the Contexts picker. If Access Groups is about who can touch which project, Agent Connectors is about whose third-party context an agent can borrow while working inside that project — group RBAC and credential scoping, two halves of the same multi-tenant story.
The surrounding changelog makes the convergence clearer. Cloud Agents Beta landed August 7. DNS logs and log improvements landed in July. Railway is layering, in sequence, the three things a self-hosted control plane exposes on day one: compute agents you schedule, name-resolution visibility you can tcpdump, and a permission model you can audit as objects. On a rented platform each arrives as a vendor-prioritized feature with a changelog date; on a cluster you own they are API objects you already have.
The self-hosted translation: the same boundary as YAML
On a Cluster API fleet the unit of tenancy is typically a namespace the way a Railway project is a unit of tenancy. The PaaS translates both to the same question: which groups can act in which projects, with which verbs?
Start with the role — the what:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: project-deployer
rules:
- apiGroups: ["", "apps", "batch"]
resources: ["pods", "deployments", "jobs", "services", "configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list"] # read-only; no create/delete — narrower than Railway's project roleDefine it once, reuse it everywhere — this is the equivalent of Railway's project role.
Then bind it per namespace to a Group subject. This is the equivalent of attaching an Access Group to a set of projects:
# team-a can deploy in team-a, not in team-b
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-deploys
namespace: team-a
subjects:
- kind: Group
name: team-a-devs # from OIDC id_token groups claim
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: project-deployer
apiGroup: rbac.authorization.k8s.ioapiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: team-a-deploys
namespace: shared-staging
subjects:
- kind: Group
name: team-a-devs
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: project-deployer
apiGroup: rbac.authorization.k8s.ioRepeat for team-b-devs → namespace: team-b. No ClusterRoleBinding — that would be the equivalent of attaching the group to every project, which is the workspace admin row in the table.
Groups arrive from your identity provider. Wire the API server to your IdP via OIDC (--oidc-issuer-url, --oidc-client-id, --oidc-groups-claim, --oidc-groups-prefix) or a webhook authenticator, and the groups claim in the token becomes the Group subject RBAC evaluates. Railway's Groups UI is a database table you click; Kubernetes groups are a token claim you issue.
Two behaviors worth calling out because they differ:
- Default deny. Kubernetes RBAC is deny by default — no binding, no access. Railway's enforcement toggle with preview exists precisely because their prior model was allow-by-default and flipping to deny needs a migration path. On your own cluster there is no toggle; the boundary exists the moment you stop granting
ClusterRoleBindingand start grantingRoleBinding. - Creator bypass. Railway's "you always see what you created" is a product affordance that prevents self-lockout on new projects. In Kubernetes, creating a namespace does not auto-bind you to it — you add that explicitly (or via an aggregated ClusterRole plus a controller that writes the binding). Stricter, more surprising to newcomers, easier to audit.
Where owning the control plane stops being the same boundary
If the previous section is "same shape, different owner," this section is where ownership actually changes what you can enforce.
1. The network boundary, not just the API boundary. Railway's Access Group controls who can see and mutate a project in the dashboard and API. It does not control whether team-a's workload can resolve or reach team-b's Service DNS name at runtime — that is the platform's private network. On your own cluster you enforce that with Kubernetes primitives the PaaS cannot expose per tenant:
NetworkPolicydefault-deny per namespace, then explicit allow — the runtime companion to RBAC's API deny. Railway has private networking; you have a firewall object you commit.- Gateway API policy (
HTTPRoute,ReferenceGrant,BackendTLSPolicy) scoped per namespace, soteam-acannot attach a route toteam-b's gateway without aReferenceGrantthe platform team grants. This is group RBAC projected into L7 routing — a dimension a hosted PaaS collapses into "environments" rather than policy objects. - OPA Gatekeeper / Kyverno guardrails: "no
RoleBindingmay referencecluster-admin," "every namespace must have aNetworkPolicy," "noLoadBalancerwithout an allow-list annotation." Railway enforces its own invariants behind the API; you enforce yours as admission policy you can read and change.
2. Audit you keep. Railway offers Members inspection per project and presumably logs access changes somewhere you can request. On your own cluster, kube-apiserver audit logs are yours — you ship them to Loki or S3, you set the audit policy, you query which Group listed which Secret at 02:14 UTC. For regulated teams this is not a nice-to-have; it is the artifact an auditor asks for, and "the vendor has logs" is not the same answer as "here are the logs."
3. Custom aggregations. Railway's project roles are the roles Railway offers. A ClusterRole with aggregationRule lets you compose roles like packages:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: platform-view
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.platform/aggregate-view: "true"
rules: [] # populated by aggregationLabel a new ClusterRole with rbac.platform/aggregate-view: "true" and every platform-view holder gains its verbs automatically. This is how a self-hosted PaaS evolves permissions without a changelog entry — new capability, new label, no migration preview to click through.
4. Agent scope as K8s identity. Railway's Agent Connectors are per-creator, per-run, private-credential — correctly scoped to the human who linked Notion or Linear. On your own fleet the agent is a ServiceAccount with its own RoleBinding and, with projected tokens or SPIFFE, a short-lived identity whose access to Notion or Sentry is itself a ClusterRole you can audit. Same intent — don't let one tenant's agent read another tenant's Sentry — different enforcement layer.
The cost of owning it (honest tradeoffs)
Owning the boundary is not free. Railway's Access Groups preview exists so a team cannot lock itself out; on your own cluster you can — a bad RoleBinding edit removes deploy access with no preview toggle to save you. Three costs you accept when you own the control plane:
- You run the API server's dependencies. etcd backups, API server upgrades, OIDC provider rotation, and the break-glass
ClusterRoleBindingfor the on-call account that can undo a bad RBAC change at 3 a.m. Managed Kubernetes (or a PaaS like Bex.co's fleet) absorbs some of this, but the RBAC objects remain yours to get right. - You operate the policy engine. Kyverno or Gatekeeper needs its own upgrade and test cycle; a badly written policy denies more than it protects. Railway tests its enforcement once for all tenants — you test yours per fleet.
- You answer the "who left this project with no owner?" question yourself. Railway surfaces "projects left without a non-admin member" before you enforce. On your own cluster that check is a
kubectlquery or a policy you write — powerful, but only if you write it.
For many teams the rented model is the right call: Access Groups is a solid, shippable RBAC primitive, and Agent Connectors correctly scope third-party context per human rather than per workspace. The point of this post is not that Railway got the model wrong — they got it close to how the underlying system already works.
The point is where the boundary lives when it matters most. When audit asks for logs you keep, when network isolation must be a NetworkPolicy object not a dashboard toggle, when a team's agent must carry a ServiceAccount identity you rotate per run — that boundary lives in the control plane. Renting it moves the enforcement date to the vendor's changelog. Owning it moves the enforcement date to your next commit.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, and keep the RBAC, Gateway API policy, and audit logs that prove who could do what, where. The control plane is yours; the PaaS just makes it usable. Star the repo on GitHub or deploy your first app today.