[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-encore-encore-go-service":3,"mdc--yjap1d-key":37,"related-org-encore-encore-go-service":720,"related-repo-encore-encore-go-service":893},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":32,"sourceUrl":35,"mdContent":36},"encore-go-service","structure services with Encore Go","Plan how to split an Encore Go application into services and lay out its directory structure. Architecture and decomposition, not first-time CLI install (that's `encore-go-getting-started`).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"encore","Encore","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fencore.png","encoredev",[13,17,20,21],{"name":14,"slug":15,"type":16},"Backend","backend","tag",{"name":18,"slug":19,"type":16},"Architecture","architecture",{"name":9,"slug":8,"type":16},{"name":22,"slug":23,"type":16},"Go","go",26,"https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills","2026-04-06T18:09:58.563643",null,5,[30,31],"claude-code","skills",{"repoUrl":25,"stars":24,"forks":28,"topics":33,"description":34},[30,31],"Agent Skills for development with Encore.","https:\u002F\u002Fgithub.com\u002Fencoredev\u002Fskills\u002Ftree\u002FHEAD\u002Fencore\u002Fgo-service","---\nname: encore-go-service\ndescription: Plan how to split an Encore Go application into services and lay out its directory structure. Architecture and decomposition, not first-time CLI install (that's `encore-go-getting-started`).\nwhen_to_use: >-\n  User is deciding monolith vs. microservices in Go, weighing \"one service or several\", drawing service boundaries, planning a multi-service system (e.g. orders + payments + inventory + shipping), creating a Go package as an Encore service, naming directories\u002Ffolders, designing systems-of-services hierarchies, or asking for a Go project layout recommendation. Trigger phrases: \"lay out the directories\", \"directory structure\", \"service boundaries\", \"one service or several\", \"monolith vs microservices\", \"where to put\", \"systems of services\", \"Go package layout\".\n---\n\n# Encore Go Service Structure\n\n## Instructions\n\nIn Encore Go, **each package with an API endpoint is automatically a service**. No special configuration needed.\n\n### Creating a Service\n\nSimply create a package with at least one `\u002F\u002Fencore:api` endpoint:\n\n```go\n\u002F\u002F user\u002Fuser.go\npackage user\n\nimport \"context\"\n\ntype User struct {\n    ID    string `json:\"id\"`\n    Email string `json:\"email\"`\n    Name  string `json:\"name\"`\n}\n\n\u002F\u002Fencore:api public method=GET path=\u002Fusers\u002F:id\nfunc GetUser(ctx context.Context, params *GetUserParams) (*User, error) {\n    \u002F\u002F This makes \"user\" a service\n}\n```\n\n### Minimal Service Structure\n\n```\nuser\u002F\n├── user.go          # API endpoints\n├── db.go            # Database (if needed)\n└── migrations\u002F      # SQL migrations\n    └── 1_create_users.up.sql\n```\n\n## Application Patterns\n\n### Single Service (Recommended Start)\n\nBest for new projects - start simple, split later if needed:\n\n```\nmy-app\u002F\n├── encore.app\n├── go.mod\n├── api.go           # All endpoints\n├── db.go            # Database\n└── migrations\u002F\n    └── 1_initial.up.sql\n```\n\n### Multi-Service\n\nFor distributed systems with clear domain boundaries:\n\n```\nmy-app\u002F\n├── encore.app\n├── go.mod\n├── user\u002F\n│   ├── user.go\n│   ├── db.go\n│   └── migrations\u002F\n├── order\u002F\n│   ├── order.go\n│   ├── db.go\n│   └── migrations\u002F\n└── notification\u002F\n    └── notification.go\n```\n\n### Large Application (System-based)\n\nGroup related services into systems:\n\n```\nmy-app\u002F\n├── encore.app\n├── go.mod\n├── commerce\u002F\n│   ├── order\u002F\n│   │   └── order.go\n│   ├── cart\u002F\n│   │   └── cart.go\n│   └── payment\u002F\n│       └── payment.go\n├── identity\u002F\n│   ├── user\u002F\n│   │   └── user.go\n│   └── auth\u002F\n│       └── auth.go\n└── comms\u002F\n    ├── email\u002F\n    │   └── email.go\n    └── push\u002F\n        └── push.go\n```\n\n## Service-to-Service Calls\n\nJust import and call the function directly - Encore handles the RPC:\n\n```go\npackage order\n\nimport (\n    \"context\"\n    \"myapp\u002Fuser\"  \u002F\u002F Import the user service\n)\n\n\u002F\u002Fencore:api auth method=GET path=\u002Forders\u002F:id\nfunc GetOrderWithUser(ctx context.Context, params *GetOrderParams) (*OrderWithUser, error) {\n    order, err := getOrder(ctx, params.ID)\n    if err != nil {\n        return nil, err\n    }\n    \n    \u002F\u002F This becomes an RPC call - Encore handles it\n    orderUser, err := user.GetUser(ctx, &user.GetUserParams{ID: order.UserID})\n    if err != nil {\n        return nil, err\n    }\n    \n    return &OrderWithUser{Order: order, User: orderUser}, nil\n}\n```\n\n## When to Split Services\n\nSplit when you have:\n\n| Signal | Action |\n|--------|--------|\n| Different scaling needs | Split (e.g., auth vs analytics) |\n| Different deployment cycles | Split |\n| Clear domain boundaries | Split |\n| Shared database tables | Keep together |\n| Tightly coupled logic | Keep together |\n| Just organizing code | Use sub-packages, not services |\n\n## Internal Helpers (Non-Service Packages)\n\nCreate packages without `\u002F\u002Fencore:api` endpoints for shared code:\n\n```\nmy-app\u002F\n├── user\u002F\n│   └── user.go       # Service (has API)\n├── order\u002F\n│   └── order.go      # Service (has API)\n└── internal\u002F\n    ├── util\u002F\n    │   └── util.go   # Not a service (no API)\n    └── validation\u002F\n        └── validate.go\n```\n\n## Guidelines\n\n- A package becomes a service when it has `\u002F\u002Fencore:api` endpoints\n- Services cannot be nested within other services\n- Start with one service, split when there's a clear reason\n- Cross-service calls look like regular function calls\n- Each service can have its own database\n- Package names should be lowercase, descriptive\n- Don't create services just for code organization - use sub-packages instead\n",{"data":38,"body":40},{"name":4,"description":6,"when_to_use":39},"User is deciding monolith vs. microservices in Go, weighing \"one service or several\", drawing service boundaries, planning a multi-service system (e.g. orders + payments + inventory + shipping), creating a Go package as an Encore service, naming directories\u002Ffolders, designing systems-of-services hierarchies, or asking for a Go project layout recommendation. Trigger phrases: \"lay out the directories\", \"directory structure\", \"service boundaries\", \"one service or several\", \"monolith vs microservices\", \"where to put\", \"systems of services\", \"Go package layout\".",{"type":41,"children":42},"root",[43,52,59,73,80,94,238,244,254,260,266,271,280,286,291,300,306,311,320,326,331,519,525,530,634,640,652,661,667,714],{"type":44,"tag":45,"props":46,"children":48},"element","h1",{"id":47},"encore-go-service-structure",[49],{"type":50,"value":51},"text","Encore Go Service Structure",{"type":44,"tag":53,"props":54,"children":56},"h2",{"id":55},"instructions",[57],{"type":50,"value":58},"Instructions",{"type":44,"tag":60,"props":61,"children":62},"p",{},[63,65,71],{"type":50,"value":64},"In Encore Go, ",{"type":44,"tag":66,"props":67,"children":68},"strong",{},[69],{"type":50,"value":70},"each package with an API endpoint is automatically a service",{"type":50,"value":72},". No special configuration needed.",{"type":44,"tag":74,"props":75,"children":77},"h3",{"id":76},"creating-a-service",[78],{"type":50,"value":79},"Creating a Service",{"type":44,"tag":60,"props":81,"children":82},{},[83,85,92],{"type":50,"value":84},"Simply create a package with at least one ",{"type":44,"tag":86,"props":87,"children":89},"code",{"className":88},[],[90],{"type":50,"value":91},"\u002F\u002Fencore:api",{"type":50,"value":93}," endpoint:",{"type":44,"tag":95,"props":96,"children":100},"pre",{"className":97,"code":98,"language":23,"meta":99,"style":99},"language-go shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F user\u002Fuser.go\npackage user\n\nimport \"context\"\n\ntype User struct {\n    ID    string `json:\"id\"`\n    Email string `json:\"email\"`\n    Name  string `json:\"name\"`\n}\n\n\u002F\u002Fencore:api public method=GET path=\u002Fusers\u002F:id\nfunc GetUser(ctx context.Context, params *GetUserParams) (*User, error) {\n    \u002F\u002F This makes \"user\" a service\n}\n","",[101],{"type":44,"tag":86,"props":102,"children":103},{"__ignoreMap":99},[104,115,124,134,143,150,159,168,177,186,195,203,212,221,230],{"type":44,"tag":105,"props":106,"children":109},"span",{"class":107,"line":108},"line",1,[110],{"type":44,"tag":105,"props":111,"children":112},{},[113],{"type":50,"value":114},"\u002F\u002F user\u002Fuser.go\n",{"type":44,"tag":105,"props":116,"children":118},{"class":107,"line":117},2,[119],{"type":44,"tag":105,"props":120,"children":121},{},[122],{"type":50,"value":123},"package user\n",{"type":44,"tag":105,"props":125,"children":127},{"class":107,"line":126},3,[128],{"type":44,"tag":105,"props":129,"children":131},{"emptyLinePlaceholder":130},true,[132],{"type":50,"value":133},"\n",{"type":44,"tag":105,"props":135,"children":137},{"class":107,"line":136},4,[138],{"type":44,"tag":105,"props":139,"children":140},{},[141],{"type":50,"value":142},"import \"context\"\n",{"type":44,"tag":105,"props":144,"children":145},{"class":107,"line":28},[146],{"type":44,"tag":105,"props":147,"children":148},{"emptyLinePlaceholder":130},[149],{"type":50,"value":133},{"type":44,"tag":105,"props":151,"children":153},{"class":107,"line":152},6,[154],{"type":44,"tag":105,"props":155,"children":156},{},[157],{"type":50,"value":158},"type User struct {\n",{"type":44,"tag":105,"props":160,"children":162},{"class":107,"line":161},7,[163],{"type":44,"tag":105,"props":164,"children":165},{},[166],{"type":50,"value":167},"    ID    string `json:\"id\"`\n",{"type":44,"tag":105,"props":169,"children":171},{"class":107,"line":170},8,[172],{"type":44,"tag":105,"props":173,"children":174},{},[175],{"type":50,"value":176},"    Email string `json:\"email\"`\n",{"type":44,"tag":105,"props":178,"children":180},{"class":107,"line":179},9,[181],{"type":44,"tag":105,"props":182,"children":183},{},[184],{"type":50,"value":185},"    Name  string `json:\"name\"`\n",{"type":44,"tag":105,"props":187,"children":189},{"class":107,"line":188},10,[190],{"type":44,"tag":105,"props":191,"children":192},{},[193],{"type":50,"value":194},"}\n",{"type":44,"tag":105,"props":196,"children":198},{"class":107,"line":197},11,[199],{"type":44,"tag":105,"props":200,"children":201},{"emptyLinePlaceholder":130},[202],{"type":50,"value":133},{"type":44,"tag":105,"props":204,"children":206},{"class":107,"line":205},12,[207],{"type":44,"tag":105,"props":208,"children":209},{},[210],{"type":50,"value":211},"\u002F\u002Fencore:api public method=GET path=\u002Fusers\u002F:id\n",{"type":44,"tag":105,"props":213,"children":215},{"class":107,"line":214},13,[216],{"type":44,"tag":105,"props":217,"children":218},{},[219],{"type":50,"value":220},"func GetUser(ctx context.Context, params *GetUserParams) (*User, error) {\n",{"type":44,"tag":105,"props":222,"children":224},{"class":107,"line":223},14,[225],{"type":44,"tag":105,"props":226,"children":227},{},[228],{"type":50,"value":229},"    \u002F\u002F This makes \"user\" a service\n",{"type":44,"tag":105,"props":231,"children":233},{"class":107,"line":232},15,[234],{"type":44,"tag":105,"props":235,"children":236},{},[237],{"type":50,"value":194},{"type":44,"tag":74,"props":239,"children":241},{"id":240},"minimal-service-structure",[242],{"type":50,"value":243},"Minimal Service Structure",{"type":44,"tag":95,"props":245,"children":249},{"className":246,"code":248,"language":50},[247],"language-text","user\u002F\n├── user.go          # API endpoints\n├── db.go            # Database (if needed)\n└── migrations\u002F      # SQL migrations\n    └── 1_create_users.up.sql\n",[250],{"type":44,"tag":86,"props":251,"children":252},{"__ignoreMap":99},[253],{"type":50,"value":248},{"type":44,"tag":53,"props":255,"children":257},{"id":256},"application-patterns",[258],{"type":50,"value":259},"Application Patterns",{"type":44,"tag":74,"props":261,"children":263},{"id":262},"single-service-recommended-start",[264],{"type":50,"value":265},"Single Service (Recommended Start)",{"type":44,"tag":60,"props":267,"children":268},{},[269],{"type":50,"value":270},"Best for new projects - start simple, split later if needed:",{"type":44,"tag":95,"props":272,"children":275},{"className":273,"code":274,"language":50},[247],"my-app\u002F\n├── encore.app\n├── go.mod\n├── api.go           # All endpoints\n├── db.go            # Database\n└── migrations\u002F\n    └── 1_initial.up.sql\n",[276],{"type":44,"tag":86,"props":277,"children":278},{"__ignoreMap":99},[279],{"type":50,"value":274},{"type":44,"tag":74,"props":281,"children":283},{"id":282},"multi-service",[284],{"type":50,"value":285},"Multi-Service",{"type":44,"tag":60,"props":287,"children":288},{},[289],{"type":50,"value":290},"For distributed systems with clear domain boundaries:",{"type":44,"tag":95,"props":292,"children":295},{"className":293,"code":294,"language":50},[247],"my-app\u002F\n├── encore.app\n├── go.mod\n├── user\u002F\n│   ├── user.go\n│   ├── db.go\n│   └── migrations\u002F\n├── order\u002F\n│   ├── order.go\n│   ├── db.go\n│   └── migrations\u002F\n└── notification\u002F\n    └── notification.go\n",[296],{"type":44,"tag":86,"props":297,"children":298},{"__ignoreMap":99},[299],{"type":50,"value":294},{"type":44,"tag":74,"props":301,"children":303},{"id":302},"large-application-system-based",[304],{"type":50,"value":305},"Large Application (System-based)",{"type":44,"tag":60,"props":307,"children":308},{},[309],{"type":50,"value":310},"Group related services into systems:",{"type":44,"tag":95,"props":312,"children":315},{"className":313,"code":314,"language":50},[247],"my-app\u002F\n├── encore.app\n├── go.mod\n├── commerce\u002F\n│   ├── order\u002F\n│   │   └── order.go\n│   ├── cart\u002F\n│   │   └── cart.go\n│   └── payment\u002F\n│       └── payment.go\n├── identity\u002F\n│   ├── user\u002F\n│   │   └── user.go\n│   └── auth\u002F\n│       └── auth.go\n└── comms\u002F\n    ├── email\u002F\n    │   └── email.go\n    └── push\u002F\n        └── push.go\n",[316],{"type":44,"tag":86,"props":317,"children":318},{"__ignoreMap":99},[319],{"type":50,"value":314},{"type":44,"tag":53,"props":321,"children":323},{"id":322},"service-to-service-calls",[324],{"type":50,"value":325},"Service-to-Service Calls",{"type":44,"tag":60,"props":327,"children":328},{},[329],{"type":50,"value":330},"Just import and call the function directly - Encore handles the RPC:",{"type":44,"tag":95,"props":332,"children":334},{"className":97,"code":333,"language":23,"meta":99,"style":99},"package order\n\nimport (\n    \"context\"\n    \"myapp\u002Fuser\"  \u002F\u002F Import the user service\n)\n\n\u002F\u002Fencore:api auth method=GET path=\u002Forders\u002F:id\nfunc GetOrderWithUser(ctx context.Context, params *GetOrderParams) (*OrderWithUser, error) {\n    order, err := getOrder(ctx, params.ID)\n    if err != nil {\n        return nil, err\n    }\n    \n    \u002F\u002F This becomes an RPC call - Encore handles it\n    orderUser, err := user.GetUser(ctx, &user.GetUserParams{ID: order.UserID})\n    if err != nil {\n        return nil, err\n    }\n    \n    return &OrderWithUser{Order: order, User: orderUser}, nil\n}\n",[335],{"type":44,"tag":86,"props":336,"children":337},{"__ignoreMap":99},[338,346,353,361,369,382,390,397,405,413,421,429,437,445,453,461,470,478,486,494,502,511],{"type":44,"tag":105,"props":339,"children":340},{"class":107,"line":108},[341],{"type":44,"tag":105,"props":342,"children":343},{},[344],{"type":50,"value":345},"package order\n",{"type":44,"tag":105,"props":347,"children":348},{"class":107,"line":117},[349],{"type":44,"tag":105,"props":350,"children":351},{"emptyLinePlaceholder":130},[352],{"type":50,"value":133},{"type":44,"tag":105,"props":354,"children":355},{"class":107,"line":126},[356],{"type":44,"tag":105,"props":357,"children":358},{},[359],{"type":50,"value":360},"import (\n",{"type":44,"tag":105,"props":362,"children":363},{"class":107,"line":136},[364],{"type":44,"tag":105,"props":365,"children":366},{},[367],{"type":50,"value":368},"    \"context\"\n",{"type":44,"tag":105,"props":370,"children":371},{"class":107,"line":28},[372,377],{"type":44,"tag":105,"props":373,"children":374},{},[375],{"type":50,"value":376},"    \"myapp\u002Fuser\"",{"type":44,"tag":105,"props":378,"children":379},{},[380],{"type":50,"value":381},"  \u002F\u002F Import the user service\n",{"type":44,"tag":105,"props":383,"children":384},{"class":107,"line":152},[385],{"type":44,"tag":105,"props":386,"children":387},{},[388],{"type":50,"value":389},")\n",{"type":44,"tag":105,"props":391,"children":392},{"class":107,"line":161},[393],{"type":44,"tag":105,"props":394,"children":395},{"emptyLinePlaceholder":130},[396],{"type":50,"value":133},{"type":44,"tag":105,"props":398,"children":399},{"class":107,"line":170},[400],{"type":44,"tag":105,"props":401,"children":402},{},[403],{"type":50,"value":404},"\u002F\u002Fencore:api auth method=GET path=\u002Forders\u002F:id\n",{"type":44,"tag":105,"props":406,"children":407},{"class":107,"line":179},[408],{"type":44,"tag":105,"props":409,"children":410},{},[411],{"type":50,"value":412},"func GetOrderWithUser(ctx context.Context, params *GetOrderParams) (*OrderWithUser, error) {\n",{"type":44,"tag":105,"props":414,"children":415},{"class":107,"line":188},[416],{"type":44,"tag":105,"props":417,"children":418},{},[419],{"type":50,"value":420},"    order, err := getOrder(ctx, params.ID)\n",{"type":44,"tag":105,"props":422,"children":423},{"class":107,"line":197},[424],{"type":44,"tag":105,"props":425,"children":426},{},[427],{"type":50,"value":428},"    if err != nil {\n",{"type":44,"tag":105,"props":430,"children":431},{"class":107,"line":205},[432],{"type":44,"tag":105,"props":433,"children":434},{},[435],{"type":50,"value":436},"        return nil, err\n",{"type":44,"tag":105,"props":438,"children":439},{"class":107,"line":214},[440],{"type":44,"tag":105,"props":441,"children":442},{},[443],{"type":50,"value":444},"    }\n",{"type":44,"tag":105,"props":446,"children":447},{"class":107,"line":223},[448],{"type":44,"tag":105,"props":449,"children":450},{},[451],{"type":50,"value":452},"    \n",{"type":44,"tag":105,"props":454,"children":455},{"class":107,"line":232},[456],{"type":44,"tag":105,"props":457,"children":458},{},[459],{"type":50,"value":460},"    \u002F\u002F This becomes an RPC call - Encore handles it\n",{"type":44,"tag":105,"props":462,"children":464},{"class":107,"line":463},16,[465],{"type":44,"tag":105,"props":466,"children":467},{},[468],{"type":50,"value":469},"    orderUser, err := user.GetUser(ctx, &user.GetUserParams{ID: order.UserID})\n",{"type":44,"tag":105,"props":471,"children":473},{"class":107,"line":472},17,[474],{"type":44,"tag":105,"props":475,"children":476},{},[477],{"type":50,"value":428},{"type":44,"tag":105,"props":479,"children":481},{"class":107,"line":480},18,[482],{"type":44,"tag":105,"props":483,"children":484},{},[485],{"type":50,"value":436},{"type":44,"tag":105,"props":487,"children":489},{"class":107,"line":488},19,[490],{"type":44,"tag":105,"props":491,"children":492},{},[493],{"type":50,"value":444},{"type":44,"tag":105,"props":495,"children":497},{"class":107,"line":496},20,[498],{"type":44,"tag":105,"props":499,"children":500},{},[501],{"type":50,"value":452},{"type":44,"tag":105,"props":503,"children":505},{"class":107,"line":504},21,[506],{"type":44,"tag":105,"props":507,"children":508},{},[509],{"type":50,"value":510},"    return &OrderWithUser{Order: order, User: orderUser}, nil\n",{"type":44,"tag":105,"props":512,"children":514},{"class":107,"line":513},22,[515],{"type":44,"tag":105,"props":516,"children":517},{},[518],{"type":50,"value":194},{"type":44,"tag":53,"props":520,"children":522},{"id":521},"when-to-split-services",[523],{"type":50,"value":524},"When to Split Services",{"type":44,"tag":60,"props":526,"children":527},{},[528],{"type":50,"value":529},"Split when you have:",{"type":44,"tag":531,"props":532,"children":533},"table",{},[534,553],{"type":44,"tag":535,"props":536,"children":537},"thead",{},[538],{"type":44,"tag":539,"props":540,"children":541},"tr",{},[542,548],{"type":44,"tag":543,"props":544,"children":545},"th",{},[546],{"type":50,"value":547},"Signal",{"type":44,"tag":543,"props":549,"children":550},{},[551],{"type":50,"value":552},"Action",{"type":44,"tag":554,"props":555,"children":556},"tbody",{},[557,571,584,596,609,621],{"type":44,"tag":539,"props":558,"children":559},{},[560,566],{"type":44,"tag":561,"props":562,"children":563},"td",{},[564],{"type":50,"value":565},"Different scaling needs",{"type":44,"tag":561,"props":567,"children":568},{},[569],{"type":50,"value":570},"Split (e.g., auth vs analytics)",{"type":44,"tag":539,"props":572,"children":573},{},[574,579],{"type":44,"tag":561,"props":575,"children":576},{},[577],{"type":50,"value":578},"Different deployment cycles",{"type":44,"tag":561,"props":580,"children":581},{},[582],{"type":50,"value":583},"Split",{"type":44,"tag":539,"props":585,"children":586},{},[587,592],{"type":44,"tag":561,"props":588,"children":589},{},[590],{"type":50,"value":591},"Clear domain boundaries",{"type":44,"tag":561,"props":593,"children":594},{},[595],{"type":50,"value":583},{"type":44,"tag":539,"props":597,"children":598},{},[599,604],{"type":44,"tag":561,"props":600,"children":601},{},[602],{"type":50,"value":603},"Shared database tables",{"type":44,"tag":561,"props":605,"children":606},{},[607],{"type":50,"value":608},"Keep together",{"type":44,"tag":539,"props":610,"children":611},{},[612,617],{"type":44,"tag":561,"props":613,"children":614},{},[615],{"type":50,"value":616},"Tightly coupled logic",{"type":44,"tag":561,"props":618,"children":619},{},[620],{"type":50,"value":608},{"type":44,"tag":539,"props":622,"children":623},{},[624,629],{"type":44,"tag":561,"props":625,"children":626},{},[627],{"type":50,"value":628},"Just organizing code",{"type":44,"tag":561,"props":630,"children":631},{},[632],{"type":50,"value":633},"Use sub-packages, not services",{"type":44,"tag":53,"props":635,"children":637},{"id":636},"internal-helpers-non-service-packages",[638],{"type":50,"value":639},"Internal Helpers (Non-Service Packages)",{"type":44,"tag":60,"props":641,"children":642},{},[643,645,650],{"type":50,"value":644},"Create packages without ",{"type":44,"tag":86,"props":646,"children":648},{"className":647},[],[649],{"type":50,"value":91},{"type":50,"value":651}," endpoints for shared code:",{"type":44,"tag":95,"props":653,"children":656},{"className":654,"code":655,"language":50},[247],"my-app\u002F\n├── user\u002F\n│   └── user.go       # Service (has API)\n├── order\u002F\n│   └── order.go      # Service (has API)\n└── internal\u002F\n    ├── util\u002F\n    │   └── util.go   # Not a service (no API)\n    └── validation\u002F\n        └── validate.go\n",[657],{"type":44,"tag":86,"props":658,"children":659},{"__ignoreMap":99},[660],{"type":50,"value":655},{"type":44,"tag":53,"props":662,"children":664},{"id":663},"guidelines",[665],{"type":50,"value":666},"Guidelines",{"type":44,"tag":668,"props":669,"children":670},"ul",{},[671,684,689,694,699,704,709],{"type":44,"tag":672,"props":673,"children":674},"li",{},[675,677,682],{"type":50,"value":676},"A package becomes a service when it has ",{"type":44,"tag":86,"props":678,"children":680},{"className":679},[],[681],{"type":50,"value":91},{"type":50,"value":683}," endpoints",{"type":44,"tag":672,"props":685,"children":686},{},[687],{"type":50,"value":688},"Services cannot be nested within other services",{"type":44,"tag":672,"props":690,"children":691},{},[692],{"type":50,"value":693},"Start with one service, split when there's a clear reason",{"type":44,"tag":672,"props":695,"children":696},{},[697],{"type":50,"value":698},"Cross-service calls look like regular function calls",{"type":44,"tag":672,"props":700,"children":701},{},[702],{"type":50,"value":703},"Each service can have its own database",{"type":44,"tag":672,"props":705,"children":706},{},[707],{"type":50,"value":708},"Package names should be lowercase, descriptive",{"type":44,"tag":672,"props":710,"children":711},{},[712],{"type":50,"value":713},"Don't create services just for code organization - use sub-packages instead",{"type":44,"tag":715,"props":716,"children":717},"style",{},[718],{"type":50,"value":719},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":721,"total":892},[722,736,748,764,780,792,808,823,840,857,867,878],{"slug":723,"name":723,"fn":724,"description":725,"org":726,"tags":727,"stars":24,"repoUrl":25,"updatedAt":735},"encore-api","build type-safe APIs with Encore","Define typed API endpoints in Encore.ts using `api(...)` from `encore.dev\u002Fapi`. Covers typed request\u002Fresponse interfaces, path\u002Fquery\u002Fheader\u002Fcookie params, request validation, and `APIError`. For raw endpoints (`api.raw()`) and inbound webhooks, use `encore-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[728,731,732],{"name":729,"slug":730,"type":16},"API Development","api-development",{"name":9,"slug":8,"type":16},{"name":733,"slug":734,"type":16},"TypeScript","typescript","2026-04-06T18:09:46.044101",{"slug":737,"name":737,"fn":738,"description":739,"org":740,"tags":741,"stars":24,"repoUrl":25,"updatedAt":747},"encore-auth","implement Encore.ts authentication","Protect Encore.ts endpoints with authentication and authorize callers. Covers `authHandler`, `Gateway`, `getAuthData`, and `auth: true`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[742,745,746],{"name":743,"slug":744,"type":16},"Auth","auth",{"name":9,"slug":8,"type":16},{"name":733,"slug":734,"type":16},"2026-04-06T18:09:47.336322",{"slug":749,"name":749,"fn":750,"description":751,"org":752,"tags":753,"stars":24,"repoUrl":25,"updatedAt":763},"encore-bucket","store files in Encore.ts buckets","Store unstructured files in Encore.ts using `Bucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[754,755,756,759,762],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":757,"slug":758,"type":16},"File Storage","file-storage",{"name":760,"slug":761,"type":16},"File Uploads","file-uploads",{"name":733,"slug":734,"type":16},"2026-05-16T05:59:52.813772",{"slug":765,"name":765,"fn":766,"description":767,"org":768,"tags":769,"stars":24,"repoUrl":25,"updatedAt":779},"encore-cache","cache data in Redis with Encore.ts","Cache data in Redis from Encore.ts using `CacheCluster` and typed keyspaces from `encore.dev\u002Fstorage\u002Fcache`. Type-safe key\u002Fvalue access with TTLs, atomic increments, and per-keyspace data shapes.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[770,771,774,775,778],{"name":14,"slug":15,"type":16},{"name":772,"slug":773,"type":16},"Caching","caching",{"name":9,"slug":8,"type":16},{"name":776,"slug":777,"type":16},"Redis","redis",{"name":733,"slug":734,"type":16},"2026-05-16T05:59:56.808328",{"slug":781,"name":781,"fn":782,"description":783,"org":784,"tags":785,"stars":24,"repoUrl":25,"updatedAt":791},"encore-code-review","review Encore.ts code","Review existing Encore.ts code for best practices and common anti-patterns.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[786,789,790],{"name":787,"slug":788,"type":16},"Code Review","code-review",{"name":9,"slug":8,"type":16},{"name":733,"slug":734,"type":16},"2026-04-06T18:10:01.123999",{"slug":793,"name":793,"fn":794,"description":795,"org":796,"tags":797,"stars":24,"repoUrl":25,"updatedAt":807},"encore-cron","schedule recurring jobs in Encore.ts","Schedule periodic \u002F recurring work in Encore.ts using `CronJob` from `encore.dev\u002Fcron`. Covers `every: \"1h\"` interval syntax and `schedule: \"0 9 * * 1\"` cron expressions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[798,801,802,803,806],{"name":799,"slug":800,"type":16},"Automation","automation",{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":804,"slug":805,"type":16},"Scheduling","scheduling",{"name":733,"slug":734,"type":16},"2026-05-16T05:59:54.146651",{"slug":809,"name":809,"fn":810,"description":811,"org":812,"tags":813,"stars":24,"repoUrl":25,"updatedAt":822},"encore-database","build Encore databases","Work with PostgreSQL in Encore.ts using `SQLDatabase` from `encore.dev\u002Fstorage\u002Fsqldb` — schema migrations and SQL queries.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[814,817,818,821],{"name":815,"slug":816,"type":16},"Database","database",{"name":9,"slug":8,"type":16},{"name":819,"slug":820,"type":16},"ORM","orm",{"name":733,"slug":734,"type":16},"2026-04-06T18:09:54.823017",{"slug":824,"name":824,"fn":825,"description":826,"org":827,"tags":828,"stars":24,"repoUrl":25,"updatedAt":839},"encore-frontend","connect frontend to Encore backend","Connect a frontend application (React, Next.js, Vue, Svelte, etc.) to an Encore.ts backend.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[829,830,833,836],{"name":9,"slug":8,"type":16},{"name":831,"slug":832,"type":16},"Frontend","frontend",{"name":834,"slug":835,"type":16},"Next.js","next-js",{"name":837,"slug":838,"type":16},"React","react","2026-04-06T18:09:56.091006",{"slug":841,"name":841,"fn":842,"description":843,"org":844,"tags":845,"stars":24,"repoUrl":25,"updatedAt":856},"encore-getting-started","build and run applications with Encore.ts","Bootstrap a brand-new Encore.ts project from zero. Only for first-time CLI install and `encore app create` — not for architecture or feature questions.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[846,847,848,849,852,853],{"name":729,"slug":730,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":850,"slug":851,"type":16},"Local Development","local-development",{"name":733,"slug":734,"type":16},{"name":854,"slug":855,"type":16},"Web Development","web-development","2026-04-06T18:10:04.885446",{"slug":858,"name":858,"fn":859,"description":860,"org":861,"tags":862,"stars":24,"repoUrl":25,"updatedAt":866},"encore-go-api","build APIs with Encore Go","Define typed API endpoints in Encore Go using `\u002F\u002Fencore:api` annotations. Covers typed request\u002Fresponse structs, path\u002Fquery\u002Fheader\u002Fcookie params, and error returns. For raw endpoints (`\u002F\u002Fencore:api raw`) and inbound webhooks, use `encore-go-webhook` instead.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[863,864,865],{"name":729,"slug":730,"type":16},{"name":9,"slug":8,"type":16},{"name":22,"slug":23,"type":16},"2026-04-06T18:09:48.578781",{"slug":868,"name":868,"fn":869,"description":870,"org":871,"tags":872,"stars":24,"repoUrl":25,"updatedAt":877},"encore-go-auth","implement authentication with Encore Go","Protect Encore Go endpoints with authentication and authorize callers. Covers `auth.AuthHandler`, `auth.UserID`, the `Authorization` header, and `\u002F\u002Fencore:api auth`.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[873,874,875,876],{"name":743,"slug":744,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":22,"slug":23,"type":16},"2026-04-06T18:09:51.065102",{"slug":879,"name":879,"fn":880,"description":881,"org":882,"tags":883,"stars":24,"repoUrl":25,"updatedAt":891},"encore-go-bucket","store files in Encore Go buckets","Store unstructured files in Encore Go using `objects.NewBucket` from `encore.dev\u002Fstorage\u002Fobjects` — uploads, images, documents, blobs.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[884,885,886,887,888],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":757,"slug":758,"type":16},{"name":22,"slug":23,"type":16},{"name":889,"slug":890,"type":16},"Storage","storage","2026-05-16T06:00:03.633918",28,{"items":894,"total":892},[895,901,907,915,923,929,937],{"slug":723,"name":723,"fn":724,"description":725,"org":896,"tags":897,"stars":24,"repoUrl":25,"updatedAt":735},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[898,899,900],{"name":729,"slug":730,"type":16},{"name":9,"slug":8,"type":16},{"name":733,"slug":734,"type":16},{"slug":737,"name":737,"fn":738,"description":739,"org":902,"tags":903,"stars":24,"repoUrl":25,"updatedAt":747},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[904,905,906],{"name":743,"slug":744,"type":16},{"name":9,"slug":8,"type":16},{"name":733,"slug":734,"type":16},{"slug":749,"name":749,"fn":750,"description":751,"org":908,"tags":909,"stars":24,"repoUrl":25,"updatedAt":763},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[910,911,912,913,914],{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":757,"slug":758,"type":16},{"name":760,"slug":761,"type":16},{"name":733,"slug":734,"type":16},{"slug":765,"name":765,"fn":766,"description":767,"org":916,"tags":917,"stars":24,"repoUrl":25,"updatedAt":779},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[918,919,920,921,922],{"name":14,"slug":15,"type":16},{"name":772,"slug":773,"type":16},{"name":9,"slug":8,"type":16},{"name":776,"slug":777,"type":16},{"name":733,"slug":734,"type":16},{"slug":781,"name":781,"fn":782,"description":783,"org":924,"tags":925,"stars":24,"repoUrl":25,"updatedAt":791},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[926,927,928],{"name":787,"slug":788,"type":16},{"name":9,"slug":8,"type":16},{"name":733,"slug":734,"type":16},{"slug":793,"name":793,"fn":794,"description":795,"org":930,"tags":931,"stars":24,"repoUrl":25,"updatedAt":807},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[932,933,934,935,936],{"name":799,"slug":800,"type":16},{"name":14,"slug":15,"type":16},{"name":9,"slug":8,"type":16},{"name":804,"slug":805,"type":16},{"name":733,"slug":734,"type":16},{"slug":809,"name":809,"fn":810,"description":811,"org":938,"tags":939,"stars":24,"repoUrl":25,"updatedAt":822},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[940,941,942,943],{"name":815,"slug":816,"type":16},{"name":9,"slug":8,"type":16},{"name":819,"slug":820,"type":16},{"name":733,"slug":734,"type":16}]