text: (window.webpackJsonp=window.webpackJsonp||[]).push([[11],{123:function(e,t,n){"use strict";n.d(t,"a",(function(){return u})),n.d(t,"b",(function(){return b}));var s=n(0),r=n.n(s);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,s)}return n}function i(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){o(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,s,r=function(e,t){if(null==e)return{};var n,s,r={},o=Object.keys(e);for(s=0;s<o.length;s++)n=o[s],t.indexOf(n)>=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(s=0;s<o.length;s++)n=o[s],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=r.a.createContext({}),d=function(e){var t=r.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=d(e.components);return r.a.createElement(l.Provider,{value:t},e.children)},p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.a.createElement(r.a.Fragment,{},t)}},h=r.a.forwardRef((function(e,t){var n=e.components,s=e.mdxType,o=e.originalType,a=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),u=d(n),h=s,b=u["".concat(a,".").concat(h)]||u[h]||p[h]||o;return n?r.a.createElement(b,i(i({ref:t},l),{},{components:n})):r.a.createElement(b,i({ref:t},l))}));function b(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var o=n.length,a=new Array(o);a[0]=h;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i.mdxType="string"==typeof e?e:s,a[1]=i;for(var l=2;l<o;l++)a[l]=n[l];return r.a.createElement.apply(null,a)}return r.a.createElement.apply(null,n)}h.displayName="MDXCreateElement"},82:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return a})),n.d(t,"metadata",(function(){return i})),n.d(t,"toc",(function(){return c})),n.d(t,"default",(function(){return d}));var s=n(3),r=n(8),o=(n(0),n(123)),a={id:"software-architecture-philosophy",title:"Software Architecture and Philosophy"},i={unversionedId:"ecosystem/software-architecture-philosophy",id:"ecosystem/software-architecture-philosophy",isDocsHomePage:!1,title:"Software Architecture and Philosophy",description:"Ory's architecture is designed along several guiding principles:",source:"@site/docs/ecosystem/software-architecture-philosophy.md",sourceDirName:"ecosystem",slug:"/ecosystem/software-architecture-philosophy",permalink:"/docs/ecosystem/software-architecture-philosophy",editUrl:"https://github.com/ory/docs/edit/master/docs/docs/ecosystem/software-architecture-philosophy.md",version:"current",lastUpdatedBy:"Vincent",lastUpdatedAt:1617015841,formattedLastUpdatedAt:"3/29/2021",frontMatter:{id:"software-architecture-philosophy",title:"Software Architecture and Philosophy"},sidebar:"docs",previous:{title:"API Design",permalink:"/docs/ecosystem/api-design"},next:{title:"ory",permalink:"/docs/cli/ory"}},c=[{value:"Architecture Philosophy",id:"architecture-philosophy",children:[{value:"The Best System Dependency is no Dependency",id:"the-best-system-dependency-is-no-dependency",children:[]},{value:"The Platform is Responsible for Horizontal Scaling",id:"the-platform-is-responsible-for-horizontal-scaling",children:[]},{value:"Configuration from Environment Variables and Configuration Files",id:"configuration-from-environment-variables-and-configuration-files",children:[]},{value:"The Process is Stateless and Disposable",id:"the-process-is-stateless-and-disposable",children:[]},{value:"Maintenance tasks run as a one-off processes",id:"maintenance-tasks-run-as-a-one-off-processes",children:[]},{value:"External Services (PostgreSQL, MySQL, ...) are Attached Resources",id:"external-services-postgresql-mysql--are-attached-resources",children:[]},{value:"Concurrency as mandated by the UNIX Process Model",id:"concurrency-as-mandated-by-the-unix-process-model",children:[]}]}],l={toc:c};function d(e){var t=e.components,n=Object(r.a)(e,["components"]);return Object(o.b)("wrapper",Object(s.a)({},l,n,{components:t,mdxType:"MDXLayout"}),Object(o.b)("p",null,"Ory's architecture is designed along several guiding principles:"),Object(o.b)("ul",null,Object(o.b)("li",{parentName:"ul"},"Minimal dependencies"),Object(o.b)("li",{parentName:"ul"},"Runs everywhere"),Object(o.b)("li",{parentName:"ul"},"Scales without effort"),Object(o.b)("li",{parentName:"ul"},"Minimize room for human and network errors")),Object(o.b)("p",null,"Our architecture leans on ",Object(o.b)("a",{parentName:"p",href:"https://www.12factor.net"},"12factor.net principles"),"\nand is designed to run best on a Container Orchestration Systems such as\nKubernetes, CloudFoundry, OpenShift, and similar projects. While it is possible\nto run the Ory stack on a RaspberryPI, the integration with the Docker and\nContainer ecosystem is best documented and supported."),Object(o.b)("h2",{id:"architecture-philosophy"},"Architecture Philosophy"),Object(o.b)("p",null,"Our philosophy and assumption of how modern software works is summarized here."),Object(o.b)("h3",{id:"the-best-system-dependency-is-no-dependency"},"The Best System Dependency is no Dependency"),Object(o.b)("p",null,"The Ory stack does not rely on (operating) system-wide dependencies such as\nJava, Apache, or other libraries. The only system-wide dependency you may\nencounter is libc / libmusl, required for standard C and POSIX functions when\nusing SQLite."),Object(o.b)("p",null,"Installing an Ory project is often just one binary away - on any architecture,\nand operating system. Our binaries are a couple of MB small and so are the\nDocker Images we distribute."),Object(o.b)("p",null,"Ory exposes HTTP(s) ports and configuration of these ports. It does not need a\nwebserver such as NGINX or Apache HTTP Server."),Object(o.b)("h3",{id:"the-platform-is-responsible-for-horizontal-scaling"},"The Platform is Responsible for Horizontal Scaling"),Object(o.b)("p",null,"The Ory stack scales without the need for any additional external service\ndependencies (e.g. etcd, Memcached) except for a RDBMS (e.g. PostgreSQL, MySQL).\nScaling horizontally is as easy as starting another process."),Object(o.b)("p",null,"The Ory Ecosystem assumes that the platform it's running on (e.g. Kubernetes,\nGoogle Cloud, Amazon Web Services, Azure, ...) is capable of Load Balancing and\ndoes not concern itself with things like Leader Election protocols or other\ncommunicating between process instances of the same project."),Object(o.b)("h3",{id:"configuration-from-environment-variables-and-configuration-files"},"Configuration from Environment Variables and Configuration Files"),Object(o.b)("p",null,"The Ory stack uses environment variables (often shortened to env vars or env)\nand files as a configuration source. All settings from a configuration file can\nalso be set using environment variables and vice versa."),Object(o.b)("p",null,"This allows systems like Kubernetes to mount, and update, configuration files\nusing volume mounts sourced from ConfigMaps and other similar resources."),Object(o.b)("p",null,"Our projects support hot-reloading of configuration files (support for hot\nreloading is not yet implemented everywhere)."),Object(o.b)("p",null,"Configuration settings are validated using JSON Schema and we try to make it as\ndifficult as possible to misconfigure our software."),Object(o.b)("h3",{id:"the-process-is-stateless-and-disposable"},"The Process is Stateless and Disposable"),Object(o.b)("p",null,"Ory processes are stateless and share-nothing. Any data that needs to persist\nmust be stored in a stateful backing service, typically a RDBMS (SQL) database."),Object(o.b)("p",null,"The processes are disposable, meaning they can be started or stopped at a\nmoment\u2019s notice. This facilitates fast elastic scaling, rapid deployment of code\nor config changes, and robustness of production deploys."),Object(o.b)("p",null,"The Ory stack strives to minimize startup time, taking no more than a few\nmilliseconds to be ready. The processes shut down gracefully when they receive a\nSIGTERM signal from the process manager. For a web process, graceful shutdown is\nachieved by ceasing to listen on the service port (thereby refusing any new\nrequests), allowing any current requests to finish, and then exiting. Implicit\nin this model is that HTTP requests are short (no more than a few seconds), or\nin the case of long polling, the client should seamlessly attempt to reconnect\nwhen the connection is lost."),Object(o.b)("h4",{id:"logs-are-stdout--stderr-streams"},"Logs are ",Object(o.b)("inlineCode",{parentName:"h4"},"stdout")," / ",Object(o.b)("inlineCode",{parentName:"h4"},"stderr")," Streams"),Object(o.b)("p",null,"The Ory stack never concerns itself with routing or storage of its output\nstream. It does not attempt to write to or manage logfiles. Instead, each\nrunning process writes its event stream, unbuffered, to stdout and stderr.\nDuring local development, the developer will view this stream in the foreground\nof their terminal to observe the app\u2019s behavior."),Object(o.b)("h3",{id:"maintenance-tasks-run-as-a-one-off-processes"},"Maintenance tasks run as a one-off processes"),Object(o.b)("p",null,"The process formation is the array of processes that are used to do the app\u2019s\nregular business (such as handling web requests) as it runs. Separately,\ndevelopers will often wish to do one-off administrative or maintenance tasks for\nthe app, such as running database migrations (e.g. ",Object(o.b)("inlineCode",{parentName:"p"},"hydra migrate sql"),")."),Object(o.b)("p",null,"One-off admin processes should be run in an identical environment as the regular\nlong-running processes of the app. They run against a release, using the same\ncodebase and config as any process run against that release. Admin code must\nship with application code to avoid synchronization issues."),Object(o.b)("h3",{id:"external-services-postgresql-mysql--are-attached-resources"},"External Services (PostgreSQL, MySQL, ...) are Attached Resources"),Object(o.b)("p",null,"A backing service is any service the app consumes over the network as part of\nits normal operation. Examples include datastores (such as MySQL or CouchDB),\nmessaging/queueing systems (such as RabbitMQ or Beanstalkd), SMTP services for\noutbound email (such as Postfix), and caching systems (such as Memcached)."),Object(o.b)("p",null,"The Ory code makes no distinction between local and third party services. To the\nprocess, both are attached resources, accessed via a URL or other\nlocator/credentials stored in the config. A deploy of a Ory project should be\nable to swap out a local MySQL database with one managed by a third party (such\nas Amazon RDS) without any changes to the app\u2019s code. Likewise, a local SMTP\nserver could be swapped with a third-party SMTP service (such as Postmark)\nwithout code changes. In both cases, only the resource handle in the config\nneeds to change."),Object(o.b)("h3",{id:"concurrency-as-mandated-by-the-unix-process-model"},"Concurrency as mandated by the UNIX Process Model"),Object(o.b)("p",null,"In the Ory Ecosystem, processes are a first class citizen. Processes take strong\ncues from the unix process model for running service daemons. Using this model,\nthe developer can architect their app to handle diverse workloads by assigning\neach type of work to a process type. For example, HTTP requests may be handled\nby a web process, and long-running background tasks handled by a worker process."))}d.isMDXComponent=!0}}]);